DBA Data[Home] [Help]

PACKAGE BODY: APPS.CZ_FCE_COMPILE

Source


1 PACKAGE BODY CZ_FCE_COMPILE AS
2 /*	$Header: czfcecpb.pls 120.91.12010000.3 2009/01/08 17:51:55 asiaston ship $		*/
3 ---------------------------------------------------------------------------------------
4 const_epoch_begin              CONSTANT DATE          := cz_utils.epoch_begin_;
5 const_epoch_end                CONSTANT DATE          := cz_utils.epoch_end_;
6 const_java_epoch_begin         CONSTANT DATE          := TO_DATE ('1970-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS');
7 
8 const_file_signature           CONSTANT RAW(4)        := HEXTORAW ('00000000');
9 
10 const_logicfile_def            CONSTANT PLS_INTEGER   := 1;
11 const_logicfile_port           CONSTANT PLS_INTEGER   := 2;
12 const_logicfile_constraint     CONSTANT PLS_INTEGER   := 3;
13 
14 const_domainorder_minfirst     CONSTANT PLS_INTEGER   := 1;
15 const_domainorder_maxfirst     CONSTANT PLS_INTEGER   := 2;
16 const_domainorder_decmax       CONSTANT PLS_INTEGER   := 3;
17 const_domainorder_incmin       CONSTANT PLS_INTEGER   := 4;
18 const_domainorder_preffalse    CONSTANT PLS_INTEGER   := 5;
19 const_domainorder_preftrue     CONSTANT PLS_INTEGER   := 6;
20 
21 const_max_localvariables       CONSTANT PLS_INTEGER   := 256;
22 const_max_registers            CONSTANT PLS_INTEGER   := 65536;
23 
24 const_constantpool_maxsize     CONSTANT PLS_INTEGER   := 65536;
25 const_constantpool_buffersize  CONSTANT PLS_INTEGER   := 32768;
26 
27 const_codememory_buffersize    CONSTANT PLS_INTEGER   := 32768;
28 
29 const_min_double               CONSTANT BINARY_DOUBLE := -1E+100D;
30 const_max_double               CONSTANT BINARY_DOUBLE := 1E+100D;
31 const_max_instance_set         CONSTANT PLS_INTEGER   := 100;
32 
33 const_context_generic          CONSTANT PLS_INTEGER   := 0;
34 const_context_target           CONSTANT PLS_INTEGER   := 1;
35 const_context_contributor      CONSTANT PLS_INTEGER   := 2;
36 const_context_literal          CONSTANT PLS_INTEGER   := 3;
37 const_context_accumulation     CONSTANT PLS_INTEGER   := 4;
38 const_context_logical          CONSTANT PLS_INTEGER   := 5;
39 const_context_forall           CONSTANT PLS_INTEGER   := 6;
40 const_context_compatible       CONSTANT PLS_INTEGER   := 7;
41 const_context_selection        CONSTANT PLS_INTEGER   := 8;
42 const_context_numeric          CONSTANT PLS_INTEGER   := 9;
43 const_context_constant         CONSTANT PLS_INTEGER   := 10;
44 const_context_heuristics       CONSTANT PLS_INTEGER   := 11;
45 const_context_aggregatesum     CONSTANT PLS_INTEGER   := 12;
46 
47 const_no_instances             CONSTANT PLS_INTEGER   := 0;
48 const_quantifier_created       CONSTANT PLS_INTEGER   := 1;
49 const_resourcesum_required     CONSTANT PLS_INTEGER   := 2;
50 
51 const_ruletype_compatible      CONSTANT PLS_INTEGER   := 0;
52 const_ruletype_forall          CONSTANT PLS_INTEGER   := 1;
53 
54 const_valuetype_unknown        CONSTANT PLS_INTEGER   := -1;
55 const_valuetype_node           CONSTANT PLS_INTEGER   := 0;
56 const_valuetype_literal        CONSTANT PLS_INTEGER   := 1;
57 const_valuetype_variable       CONSTANT PLS_INTEGER   := 2;
58 const_valuetype_selection      CONSTANT PLS_INTEGER   := 3;
59 const_valuetype_sysprop        CONSTANT PLS_INTEGER   := 4;
60 
61 const_textid_resultnotvalid    CONSTANT PLS_INTEGER   := 74;
62 const_mask_all_usages          CONSTANT VARCHAR2(16) := '0000000000000000';
63 const_mask_no_usages           CONSTANT VARCHAR2(16) := 'FFFFFFFFFFFFFFFF';
64 
65 g_sw_msg_prefix                VARCHAR2(4000) := NULL;
66 g_se_msg_prefix                VARCHAR2(4000) := NULL;
67 
68 /*------------------------------------------------------------------------------------
69   List of tags:
70   -------------
71     #<path in model def>
72     #<constant pool format>
73     #<problem>
74     #<dio integration>
75     #<optimization>
76     #<optimization-reverseport>
77     #<verification>
78     #<temporary>
79     #<should never happen>
80     #<important>
81     #<logic files handling>
82     #<todo>
83 -------------------------------------------------------------------------------------*/
84 --------------------------------------------------------------------------------------
85 /*------------------------------------------------------------------------------------
86   Hash keys for local variables:
87   ------------------------------
88     model defs:                               psnodeid
89     instance quantifiers:                     psnodeid1_psnodeid2_..._psnodeidN
90     any node except targets and contributors: psnodeid-explid
91 
92     temporary local variables (never need to be re-generated): 'var', 'iq', 'exp'
93 
94   Hash keys for registers:
95   ------------------------
96     instance quantifies in accumulator rules: psnodeid1_psnodeid2_..._psnodeidN
97     targets in accumulator rules:             psnodeid:explid
98     contributors to a target:                 <number>$psnodeid:explid
99     generic assistant variables:              _<assistant_var_id>
100     dedicated register for contributions:     'value'
101 
102   Variable names:
103   ---------------
104     feature-property assistant variable:      _psnodeid_propertyid
105 -------------------------------------------------------------------------------------*/
106 -- Function that is be used to get the message text for the not translated
107 -- system messages.
108 -- Note: It is temporarily used for new FCE user warnings and errors till they are
109 --       defined in FND_NEW_MESSAGES table.
110 FUNCTION GET_NOT_TRANSLATED_TEXT(inMessageName IN VARCHAR2,
111                   inToken1 IN VARCHAR2 DEFAULT NULL, inValue1 IN VARCHAR2 DEFAULT NULL,
112                   inToken2 IN VARCHAR2 DEFAULT NULL, inValue2 IN VARCHAR2 DEFAULT NULL,
113                   inToken3 IN VARCHAR2 DEFAULT NULL, inValue3 IN VARCHAR2 DEFAULT NULL,
114                   inToken4 IN VARCHAR2 DEFAULT NULL, inValue4 IN VARCHAR2 DEFAULT NULL,
115                   inToken5 IN VARCHAR2 DEFAULT NULL, inValue5 IN VARCHAR2 DEFAULT NULL,
116                   inToken6 IN VARCHAR2 DEFAULT NULL, inValue6 IN VARCHAR2 DEFAULT NULL) RETURN VARCHAR2 IS
117   v_String  VARCHAR2(4000) := NULL;
118 BEGIN
119   IF inToken1 IS NULL THEN
120     RETURN inMessageName;
121   ELSE
122     v_String := replace(inMessageName, '^'||inToken1, inValue1);
123     IF inToken2 IS NULL THEN
124       RETURN v_String;
125     ELSE
126       v_String := replace(v_String, '^'||inToken2, inValue2);
127       IF inToken3 IS NULL THEN
128         RETURN v_String;
129       ELSE
130         v_String := replace(v_String, '^'||inToken3, inValue3);
131         IF inToken4 IS NULL THEN
132           RETURN v_String;
133         ELSE
134           v_String := replace(v_String, '^'||inToken4, inValue4);
135           IF inToken5 IS NULL THEN
136             RETURN v_String;
137           ELSE
138             v_String := replace(v_String, '^'||inToken5, inValue5);
139             IF inToken6 IS NULL THEN
140              RETURN v_String;
141             ELSE
142              v_String := replace(v_String, '^'||inToken5, inValue5);
143             END IF; --Token6
144           END IF; -- Token5
145         END IF; -- Token4
146       END IF; -- Token3
147     END IF; -- Token2
148   END IF; -- Token1
149   RETURN v_String;
150 END GET_NOT_TRANSLATED_TEXT;
151 -------------------------------------------------------------------------------------
152 -- Following three report_and_raise procedures log the message to cz_db_logs
153 -- and raise the appropriate exception
154 
155 -- This procedure reports user warning and by default raises
156 -- CZ_LOGICGEN_WARNING exception. To stop raising exception
157 -- set the p_raise_exception flag to FALSE.
158 PROCEDURE report_and_raise_warning(
159       p_message         IN VARCHAR2
160     , p_run_id          IN NUMBER
161     , p_model_id        IN NUMBER
162     , p_ps_node_id      IN NUMBER DEFAULT NULL
163     , p_rule_id         IN NUMBER DEFAULT NULL
164     , p_error_stack     IN VARCHAR2 DEFAULT NULL
165     , p_raise_exception IN BOOLEAN DEFAULT TRUE ) IS
166 BEGIN
167     CZ_FCE_COMPILE_UTILS.REPORT_WARNING(
168                 p_message => p_message,
169                 p_run_id => p_run_id,
170                 p_model_id => p_model_id,
171                 p_ps_node_id => p_ps_node_id,
172                 p_rule_id => p_rule_id,
173                 p_error_stack => p_error_stack
174     );
175     IF p_raise_exception THEN
176         RAISE CZ_LOGICGEN_WARNING;
177     END IF;
178 END report_and_raise_warning;
179 -------------------------------------------------------------------------------------
180 -- This procedure reports user system warning and by default raises
181 -- CZ_LOGICGEN_WARNING exception. This procedure prefixes the
182 -- given message with generic system warning note. To stop raising exception
183 -- set the p_raise_exception flag to FALSE.
184 PROCEDURE report_and_raise_sys_warning(
185       p_message         IN VARCHAR2
186     , p_run_id          IN NUMBER
187     , p_model_id        IN NUMBER
188     , p_ps_node_id      IN NUMBER DEFAULT NULL
189     , p_rule_id         IN NUMBER DEFAULT NULL
190     , p_error_stack     IN VARCHAR2 DEFAULT NULL
191     , p_raise_exception IN BOOLEAN DEFAULT TRUE ) IS
192 BEGIN
193     IF g_sw_msg_prefix IS NULL THEN
194          -- System Warning: Generally caused by environment or system issues.
195          g_sw_msg_prefix := CZ_UTILS.GET_TEXT(CZ_FCE_SW_GENERIC_PREFIX);
196     END IF;
197     CZ_FCE_COMPILE_UTILS.REPORT_WARNING(
198                 p_message => g_sw_msg_prefix || p_message,
199                 p_run_id => p_run_id,
200                 p_model_id => p_model_id,
201                 p_ps_node_id => p_ps_node_id,
202                 p_rule_id => p_rule_id,
203                 p_error_stack => p_error_stack
204     );
205     IF p_raise_exception THEN
206         RAISE CZ_LOGICGEN_SYS_WARNING;
207     END IF;
208 END report_and_raise_sys_warning;
209 -------------------------------------------------------------------------------------
210 -- This procedure reports user error and by default raises
211 -- CZ_LOGICGEN_ERROR exception. To stop raising exception
212 -- set the p_raise_exception flag to FALSE.
213 PROCEDURE report_and_raise_error(
214       p_message         IN VARCHAR2
215     , p_run_id          IN NUMBER
216     , p_model_id        IN NUMBER
217     , p_ps_node_id      IN NUMBER DEFAULT NULL
218     , p_rule_id         IN NUMBER DEFAULT NULL
219     , p_error_stack     IN VARCHAR2 DEFAULT NULL
220     , p_raise_exception IN BOOLEAN DEFAULT TRUE ) IS
221 BEGIN
222     CZ_FCE_COMPILE_UTILS.REPORT_ERROR(
223                 p_message => p_message,
224                 p_run_id => p_run_id,
225                 p_model_id => p_model_id,
226                 p_ps_node_id => p_ps_node_id,
227                 p_rule_id => p_rule_id,
228                 p_error_stack => p_error_stack
229     );
230     IF p_raise_exception THEN
231         RAISE CZ_LOGICGEN_ERROR;
232     END IF;
233 END report_and_raise_error;
234 -------------------------------------------------------------------------------------
235 -- This procedure reports system error and by default raises
236 -- CZ_LOGICGEN_ERROR exception. This procedure prefixes the
237 -- given message with generic system error note. To stop raising exception
238 -- set the p_raise_exception flag to FALSE.
239 PROCEDURE report_and_raise_sys_error(
240       p_message         IN VARCHAR2
241     , p_run_id          IN NUMBER
242     , p_model_id        IN NUMBER
243     , p_ps_node_id      IN NUMBER DEFAULT NULL
244     , p_rule_id         IN NUMBER DEFAULT NULL
245     , p_error_stack     IN VARCHAR2 DEFAULT NULL
246     , p_raise_exception IN BOOLEAN DEFAULT TRUE ) IS
247 BEGIN
248     IF g_se_msg_prefix IS NULL THEN
249          -- System Error: Generally caused by environment or system issues.
250          g_se_msg_prefix := CZ_UTILS.GET_TEXT(CZ_FCE_SE_GENERIC_PREFIX);
251     END IF;
252     CZ_FCE_COMPILE_UTILS.REPORT_SYSTEM_ERROR(
253                 p_message => g_se_msg_prefix || p_message,
254                 p_run_id => p_run_id,
255                 p_model_id => p_model_id,
256                 p_ps_node_id => p_ps_node_id,
257                 p_rule_id => p_rule_id,
258                 p_error_stack => p_error_stack
259     );
260     IF p_raise_exception THEN
261         RAISE CZ_LOGICGEN_SYS_ERROR;
262     END IF;
263 END report_and_raise_sys_error;
264 -------------------------------------------------------------------------------------
265 --This procedure compiles logic for a model specified by either a database id
266 --
267 --p_object_id: Database model id. Used when the second parameter is null.
268 --x_run_id: Unique id of the compilation session.
269 --p_two_phase_commit: 0 - compiler commits the logic, 1 - no commit.
270 --p_debug_mode: 0 - normal mode, 1 - debug mode.
271 
272 PROCEDURE compile_logic_ ( p_object_id        IN NUMBER
273                          , x_run_id           IN OUT NOCOPY NUMBER
274                          , p_two_phase_commit IN PLS_INTEGER
275                          , p_debug_mode       IN PLS_INTEGER
276                          ) IS
277 
278   v_index                      PLS_INTEGER;
279 
280   h_psnid_psnodetype           type_node_hashtable;
281   h_psnid_detailedtype         type_node_hashtable;
282   h_psnid_decimalqtyflag       type_flag_hashtable;
283   h_psnid_persistentnodeid     type_node_hashtable;
284   h_psnid_devlprojectid        type_node_hashtable;
285   h_psnid_parentid             type_node_hashtable;
286   h_psnid_name                 type_name_hashtable;
287 
288   h_devlid_modelvisited        type_data_hashtable;
289   h_psnid_createreverseport    type_data_hashtable;
290   h_psnid_numberofchildren     type_data_hashtable;
291   h_psnid_lastchildindex       type_data_hashtable;
292   h_psnid_backindex            type_data_hashtable;
293   h_psnid_propid_isvalid       type_bool_hashtable;
294 
295   t_psn_psnodeid               type_number_table;
296   t_psn_parentid               type_number_table;
297   t_psn_itemid                 type_number_table;
298   t_psn_minimum                type_number_table;
299   t_psn_maximum                type_number_table;
300   t_psn_name                   type_varchar4000_table;
301   t_psn_intltextid             type_number_table;
302   t_psn_minimumselected        type_number_table;
303   t_psn_maximumselected        type_number_table;
304   t_psn_psnodetype             type_number_table;
305   t_psn_initialvalue           type_varchar4000_table;
306   t_psn_virtualflag            type_varchar1_table;
307   t_psn_featuretype            type_number_table;
308   t_psn_bomrequiredflag        type_varchar1_table;
309   t_psn_referenceid            type_number_table;
310   t_psn_persistentnodeid       type_number_table;
311   t_psn_effectivefrom          type_date_table;
312   t_psn_effectiveuntil         type_date_table;
313   t_psn_effectiveusagemask     type_varchar16_table;
314   t_psn_effectivitysetid       type_number_table;
315   t_psn_decimalqtyflag         type_varchar1_table;
316   t_psn_ibtrackable            type_varchar1_table;
317   t_psn_accumulatorflag        type_varchar1_table;
318   t_psn_initialnumvalue        type_number_table;
319   t_psn_instantiableflag       type_varchar1_table;
320   t_psn_shippableitemflag      type_varchar1_table;
321   t_psn_invtransactflag        type_varchar1_table;
322   t_psn_atoflag                type_varchar1_table;
323   t_psn_serialitemflag         type_varchar1_table;
324   t_psn_countedoptionsflag     type_varchar1_table;
325   t_psn_devlprojectid          type_number_table;
326   t_psn_domainorder            type_number_table;
327   t_psn_reverseportid          type_number_table;
328   t_psn_maxqtyperoption        type_number_table;
329   t_psn_detailedtype           type_number_table;
330 
331   h_explid_referencepath       type_numbertable_hashtable;
332   h_psnid_modelpath            type_numbertable_hashtable;
333   h_psnid_explid_completepath  type_numbertable_hashtable;
334 
335   t_effset_effectivitysetid    type_number_table;
336   t_effset_effectivefrom       type_date_table;
337   t_effset_effectiveuntil      type_date_table;
338 
339   h_effsetid_effectivefrom     type_date_hashtable;
340   h_effsetid_effectiveuntil    type_date_hashtable;
341 ---------------------------------------------------------------------------------------
342   -- Scope: compile_logic_
343   PROCEDURE debug ( p_message IN VARCHAR2 ) IS
344   BEGIN
345 
346     IF ( p_debug_mode = 1 ) THEN
347 
348       CZ_FCE_COMPILE_UTILS.REPORT_INFO(
349                 p_message => p_message,
350                 p_run_id => - x_run_id,
351                 p_model_id => null,
352                 p_ps_node_id => null,
353                 p_rule_id => null,
354                 p_error_stack => null
355      );
356     END IF;
357   END debug;
358 ---------------------------------------------------------------------------------------
359   FUNCTION build_model_path ( p_node_id IN NUMBER ) RETURN type_number_table IS
360 
361        l_node        NUMBER;
362        l_key         VARCHAR2(4000) := TO_CHAR ( p_node_id );
363        tl_id_path    type_number_table;
364 
365   BEGIN
366 
367        IF ( h_psnid_modelpath.EXISTS ( l_key )) THEN RETURN h_psnid_modelpath ( l_key ); END IF;
368 
369        --When participant is a Bom Reference, we need to switch to the referenced Bom Model and
370        --have it in the path. This way generate_path correctly generate instance quantifier for
371        --the referring reference.
372 
373        IF ( h_psnid_psnodetype ( l_key ) = h_psntypes ('bommodel')) THEN
374 
375           tl_id_path ( 1 ) := p_node_id;
376 
377        END IF;
378 
379        l_node := p_node_id;
380 
381        WHILE ( h_psnid_parentid ( TO_CHAR ( l_node )) IS NOT NULL ) LOOP
382 
383          tl_id_path ( tl_id_path.COUNT + 1 ) := l_node;
384          l_node := h_psnid_parentid ( TO_CHAR ( l_node ));
385 
386        END LOOP;
387 
388        h_psnid_modelpath ( l_key ) := tl_id_path;
389 
390        RETURN tl_id_path;
391 
392      EXCEPTION
393         WHEN OTHERS THEN
394 
395            tl_id_path.DELETE;
396            RETURN tl_id_path;
397 
398   END build_model_path;
399 ----------------------------------------------------------------------------------
400   FUNCTION ps_node_id_table_to_string ( p_node_id_table type_number_table ) RETURN VARCHAR2 IS
401 
402       l_path VARCHAR2(4000) := NULL;
403 
404   BEGIN
405 
406        IF ( p_node_id_table IS NULL OR p_node_id_table.COUNT = 0 ) THEN
407 
408          RETURN NULL;
409 
410        ELSE
411 
412          FOR iNode IN REVERSE 1 .. p_node_id_table.COUNT LOOP
413 
414            IF ( iNode = p_node_id_table.COUNT ) THEN
415 
416                l_path := l_path || h_psnid_name ( p_node_id_table ( iNode ));
417 
418            ELSE
419 
420                l_path := l_path || '.' || h_psnid_name ( p_node_id_table ( iNode ));
421 
422            END IF;
423          END LOOP;
424 
425          RETURN l_path;
426 
427        END IF;
428   EXCEPTION
429      WHEN OTHERS THEN
430 
431         RETURN NULL;
432 
433   END ps_node_id_table_to_string;
434 ---------------------------------------------------------------------------------------
435   PROCEDURE read_model_data ( p_component_id IN NUMBER ) IS
436 
437      l_psn_psnodeid             type_number_table;
438      l_psn_parentid             type_number_table;
439      l_psn_itemid               type_number_table;
440      l_psn_minimum              type_number_table;
441      l_psn_maximum              type_number_table;
442      l_psn_name                 type_varchar4000_table;
443      l_psn_intltextid           type_number_table;
444      l_psn_minimumselected      type_number_table;
445      l_psn_maximumselected      type_number_table;
446      l_psn_psnodetype           type_number_table;
447      l_psn_initialvalue         type_varchar4000_table;
448      l_psn_virtualflag          type_varchar1_table;
449      l_psn_featuretype          type_number_table;
450      l_psn_bomrequiredflag      type_varchar1_table;
451      l_psn_referenceid          type_number_table;
452      l_psn_persistentnodeid     type_number_table;
453      l_psn_effectivefrom        type_date_table;
454      l_psn_effectiveuntil       type_date_table;
455      l_psn_effectiveusagemask   type_varchar16_table;
456      l_psn_effectivitysetid     type_number_table;
457      l_psn_decimalqtyflag       type_varchar1_table;
458      l_psn_ibtrackable          type_varchar1_table;
459      l_psn_accumulatorflag      type_varchar1_table;
460      l_psn_initialnumvalue      type_number_table;
461      l_psn_instantiableflag     type_varchar1_table;
462      l_psn_shippableitemflag    type_varchar1_table;
463      l_psn_invtransactflag      type_varchar1_table;
464      l_psn_atoflag              type_varchar1_table;
465      l_psn_serialitemflag       type_varchar1_table;
466      l_psn_countedoptionsflag   type_varchar1_table;
467      l_psn_devlprojectid        type_number_table;
468      l_psn_domainorder          type_number_table;
469      l_psn_reverseportid        type_number_table;
470      l_psn_maxqtyperoption      type_number_table;
471      l_psn_detailedtype         type_number_table;
472 
473      l_port_table               type_integer_table;
474      l_reverseport_table        type_integer_table;
475      l_index                    PLS_INTEGER;
476      l_parent_id                VARCHAR2(4000);
477      l_node_id                  VARCHAR2(4000);
478 
479      l_model_id                 NUMBER;
480      ----------------------------------------------------------------------------------
481      PROCEDURE set_token ( p_mark IN VARCHAR2 ) IS
482      BEGIN
483 
484         t_psn_psnodetype ( v_index ) := h_psntypes ( p_mark );
485         t_psn_psnodeid ( v_index ) := p_component_id;
486         t_psn_devlprojectid ( v_index ) := p_component_id;
487         t_psn_parentid ( v_index ) := NULL;
488 
489         v_index := v_index + 1;
490 
491      END set_token;
492      ----------------------------------------------------------------------------------
493   BEGIN --> read_model_data
494 
495       --This procedure reads model hierarchy structure in a certain format that is used by
496       --compile_logic_file procedure. The format uses tokens - dummy nodes of special type
497       --that are embedded into the structure (see the above procedure set_token for the
498       --columns that are used in the definition). The resulting memory structure looks
499       --like this:
500 
501       --'beginstructure'
502       --  <model_data>
503       --    'beginstructure'
504       --       <child_model_data>
505       --          ...
506       --       'beginport'
507       --         <child_model_ports>
508       --       'endport'
509       --     'endstructure'
510       --     ...
511       --  'beginport'
512       --     <model_ports>
513       --  'endport'
514       --  'beginrule'
515       --     <reverse_ports>
516       --  'endrule'
517       --'endstructure'
518 
519       --Each model data is contained only once in this hierarchy, when the model is first referenced.
520       --The port section of the referencing model cannot be processed before the referenced model is
521       --processed.
522 
523       h_devlid_modelvisited ( TO_CHAR (p_component_id)) := 1;
524 
525       SELECT ps_node_id, parent_id, item_id, minimum, maximum, name, intl_text_id, minimum_selected,
526              maximum_selected, ps_node_type, initial_value, virtual_flag, feature_type, bom_required_flag,
527              reference_id, persistent_node_id, effective_from, effective_until, effective_usage_mask,
528              effectivity_set_id, decimal_qty_flag, ib_trackable, accumulator_flag, initial_num_value,
529              instantiable_flag, shippable_item_flag, inventory_transactable_flag, assemble_to_order_flag,
530              serializable_item_flag, counted_options_flag, devl_project_id, domain_order,
531              reverse_connector_id, max_qty_per_option
532         BULK COLLECT INTO
533              l_psn_psnodeid, l_psn_parentid, l_psn_itemid, l_psn_minimum, l_psn_maximum, l_psn_name,
534              l_psn_intltextid, l_psn_minimumselected, l_psn_maximumselected, l_psn_psnodetype,
535              l_psn_initialvalue, l_psn_virtualflag, l_psn_featuretype, l_psn_bomrequiredflag,
536              l_psn_referenceid, l_psn_persistentnodeid, l_psn_effectivefrom, l_psn_effectiveuntil,
537              l_psn_effectiveusagemask, l_psn_effectivitysetid, l_psn_decimalqtyflag, l_psn_ibtrackable,
538              l_psn_accumulatorflag, l_psn_initialnumvalue, l_psn_instantiableflag, l_psn_shippableitemflag,
539              l_psn_invtransactflag, l_psn_atoflag, l_psn_serialitemflag, l_psn_countedoptionsflag,
540              l_psn_devlprojectid, l_psn_domainorder, l_psn_reverseportid, l_psn_maxqtyperoption
541         FROM cz_ps_nodes
542        WHERE deleted_flag = '0'
543        START WITH ps_node_id = p_component_id
544      CONNECT BY PRIOR deleted_flag = '0' AND PRIOR ps_node_id = parent_id;
545 
546      --Note: the condition on PRIOR deleted_flag is included to handle the cases when children of a deleted
547      --parent are not deleted, for example when options of a deleted option feature still have the value of
548      --deleted_flag = '0'. If such situation is not possible, the condition can be removed if it slows down
549      --the query.
550 
551      IF (l_psn_psnodeid.COUNT > 0) THEN
552 
553         set_token ('beginstructure');
554 
555         FOR i IN 1..l_psn_psnodeid.COUNT LOOP
556 
557            l_psn_virtualflag ( i ) := NVL ( l_psn_virtualflag ( i ), '1' );
558            l_psn_instantiableflag ( i ) := NVL ( l_psn_instantiableflag ( i ), h_instantiability ('mandatory'));
559            l_psn_detailedtype ( i ) := l_psn_psnodetype ( i );
560 
561            --#<important>
562            --If splitting the detailed type further, it is necessary to find all existing references
563            --to this detailed type in the code to see if they need to be modified.
564 
565            IF ( l_psn_psnodetype ( i ) = h_psntypes ('feature')) THEN
566 
567               l_psn_detailedtype ( i ) := l_psn_featuretype ( i );
568 
569            ELSIF ( l_psn_psnodetype ( i ) = h_psntypes ('component')) THEN
570 
571               IF ( l_psn_parentid ( i ) IS NULL ) THEN
572 
573                 l_psn_detailedtype ( i ) := h_psntypes ('root');
574 
575               ELSIF ( l_psn_virtualflag ( i ) = '1' ) THEN
576 
577                 l_psn_detailedtype ( i ) := h_psntypes ('singleton');
578 
579               END IF;
580            END IF;
581 
582            t_psn_psnodeid ( v_index ) := l_psn_psnodeid ( i );
583            t_psn_parentid ( v_index ) := l_psn_parentid ( i );
584            t_psn_itemid ( v_index ) := l_psn_itemid ( i );
585            t_psn_minimum ( v_index ) := l_psn_minimum ( i );
586            t_psn_maximum ( v_index ) := l_psn_maximum ( i );
587            t_psn_name ( v_index ) := l_psn_name ( i );
588            t_psn_intltextid ( v_index ) := l_psn_intltextid ( i );
589            t_psn_minimumselected ( v_index ) := l_psn_minimumselected ( i );
590            t_psn_maximumselected ( v_index ) := l_psn_maximumselected ( i );
591            t_psn_psnodetype ( v_index ) := l_psn_psnodetype ( i );
592            t_psn_initialvalue ( v_index ) := l_psn_initialvalue ( i );
593            t_psn_virtualflag ( v_index ) := l_psn_virtualflag ( i );
594            t_psn_featuretype ( v_index ) := l_psn_featuretype ( i );
595            t_psn_bomrequiredflag ( v_index ) := l_psn_bomrequiredflag ( i );
596            t_psn_referenceid ( v_index ) := l_psn_referenceid ( i );
597            t_psn_persistentnodeid ( v_index ) := l_psn_persistentnodeid ( i );
598            t_psn_effectivefrom ( v_index ) := l_psn_effectivefrom ( i );
599            t_psn_effectiveuntil ( v_index ) := l_psn_effectiveuntil ( i );
600            t_psn_effectiveusagemask ( v_index ) := l_psn_effectiveusagemask ( i );
601            t_psn_effectivitysetid ( v_index ) := l_psn_effectivitysetid ( i );
602            t_psn_decimalqtyflag ( v_index ) := l_psn_decimalqtyflag ( i );
603            t_psn_ibtrackable ( v_index ) := l_psn_ibtrackable ( i );
604            t_psn_accumulatorflag ( v_index ) := l_psn_accumulatorflag ( i );
605            t_psn_initialnumvalue ( v_index ) := l_psn_initialnumvalue ( i );
606            t_psn_instantiableflag ( v_index ) := l_psn_instantiableflag ( i );
607            t_psn_shippableitemflag ( v_index ) := l_psn_shippableitemflag ( i );
608            t_psn_invtransactflag ( v_index ) := l_psn_invtransactflag ( i );
609            t_psn_atoflag ( v_index ) := l_psn_atoflag ( i );
610            t_psn_serialitemflag ( v_index ) := l_psn_serialitemflag ( i );
611            t_psn_countedoptionsflag ( v_index ) := l_psn_countedoptionsflag ( i );
612            t_psn_devlprojectid ( v_index ) := l_psn_devlprojectid ( i );
613            t_psn_domainorder ( v_index ) := l_psn_domainorder ( i );
614            t_psn_reverseportid ( v_index ) := l_psn_reverseportid ( i );
615            t_psn_maxqtyperoption ( v_index ) := l_psn_maxqtyperoption ( i );
616            t_psn_detailedtype ( v_index ) := l_psn_detailedtype ( i );
617 
618            l_node_id := TO_CHAR ( l_psn_psnodeid ( i ));
619 
620            h_psnid_backindex ( l_node_id ) := v_index;
621            h_psnid_numberofchildren ( l_node_id  ) := 0;
622 
623            --If node is assigned to an effectivity set, its effectivities should be taken from this set.
624 
625            IF ( l_psn_effectivitysetid ( i ) IS NOT NULL ) THEN
626               IF ( NOT h_effsetid_effectivefrom.EXISTS ( TO_CHAR ( l_psn_effectivitysetid ( i )))) THEN
627 
628                   report_and_raise_warning (
629                       p_message => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SW_NODEINCORRECTEFFSET,
630                           'NODE_NAME',
631                           CZ_FCE_COMPILE_UTILS.GET_NODE_PATH ( l_psn_psnodeid ( i ),
632                             ps_node_id_table_to_string (
633                                 build_model_path ( l_psn_psnodeid ( i )))),
634                           'MODEL_NAME',
635                           CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH ( p_component_id, null )),
636                       p_run_id => x_run_id,
637                       p_model_id => p_component_id,
638                       p_raise_exception => FALSE
639                   );
640 
641               ELSE
642 
643                   t_psn_effectivefrom ( v_index ) := h_effsetid_effectivefrom ( TO_CHAR ( l_psn_effectivitysetid ( i )));
644                   t_psn_effectiveuntil ( v_index ) := h_effsetid_effectiveuntil ( TO_CHAR ( l_psn_effectivitysetid ( i )));
645 
646               END IF;
647            END IF;
648 
649            --This is a global variable, it is used to index the whole hierarchy, in particular,
650            --it needs to be increased -before- following the references. So, caution should be
651            --exercised when moving this statement.
652 
653            v_index := v_index + 1;
654 
655            h_psnid_psnodetype ( l_node_id ) := l_psn_psnodetype ( i );
656            h_psnid_detailedtype ( l_node_id ) := l_psn_detailedtype ( i );
657            h_psnid_decimalqtyflag ( l_node_id ) := l_psn_decimalqtyflag ( i );
658            h_psnid_persistentnodeid ( l_node_id ) := l_psn_persistentnodeid ( i );
659            h_psnid_devlprojectid( l_node_id ) := l_psn_devlprojectid ( i );
660 
661            --#<path in model def>
662            --This two arrays are introduced to be able to generate a full model path to be used when
663            --creating model defs. Currently this is used only for debugging purposes. For example in
664            --the following situation:
665            --
666            --M
667            --|_C1
668            --|  |_C3
669            --|_C2
670            --   |_C3
671            --
672            --C3 can be different node with the same name. When creating XML from byte-code it will be
673            --not clear which model def for C3 belongs under which component.
674 
675            h_psnid_name( l_node_id ) := l_psn_name ( i );
676            h_psnid_parentid( l_node_id ) := l_psn_parentid ( i );
677 
678            --We have to do this here and not earlier as we may need the hash tables above to build to
679            --construct the path in the model.
680 
681            IF ( l_psn_psnodetype ( i ) = h_psntypes ('connector')) THEN
682                -- Node ^NODE_NAME in Model ^MODEL_NAME is a Connector. In this release, Connectors are only supported in Orginal Configuration Engine type models.
683                report_and_raise_error (
684                     p_message => CZ_UTILS.GET_TEXT ( CZ_FCE_E_CONNECTNOTSUPPORTED,
685                           'NODE_NAME',
686                           CZ_FCE_COMPILE_UTILS.GET_NODE_PATH ( l_psn_psnodeid ( i ),
687                               ps_node_id_table_to_string(
688                                 build_model_path(l_psn_psnodeid ( i )) )
689                               ),
690                           'MODEL_NAME',
691                           CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH ( p_component_id )),
692                     p_run_id => x_run_id,
693                     p_model_id => p_component_id
694                );
695            END IF;
696 
697            IF ( l_psn_psnodetype(i) IN ( h_psntypes ('reference'), h_psntypes ('connector')) OR
698                 ( l_psn_psnodetype(i) = h_psntypes('component') AND l_psn_parentid ( i ) IS NOT NULL)) THEN
699 
700                --References, connectors and all non-root component variables go to the port file.
701 
702                l_port_table ( l_port_table.COUNT + 1 ) := i;
703 
704                --Now handle additional control tables for reverse ports. It is important to do it here before
705                --following the reference. The reason is that although Solver does not care on which of the
706                --reverse ports we call the setReversePort method, from the DIO integration point of view we
707                --need to call it on the 'parent' port.
708 
709                IF ( l_psn_reverseportid ( i ) IS NOT NULL AND ( NOT h_psnid_createreverseport.EXISTS ( TO_CHAR ( l_psn_reverseportid ( i ))))) THEN
710 
711                    --This port has a reverse port defined, so we need to call setReversePort either on this
712                    --port, or on the other port. If the other port has not been added to the rule section,
713                    --add this one and remember it.
714 
715                    l_reverseport_table ( l_reverseport_table.COUNT + 1 ) := i;
716                    h_psnid_createreverseport ( TO_CHAR ( l_psn_psnodeid ( i ))) := 1;
717 
718                    IF ( NOT h_psnid_devlprojectid.EXISTS ( TO_CHAR ( l_psn_reverseportid ( i )))) THEN
719 
720                       --The model containing the referring port has not been processed, we need to process this model
721                       --to make sure that its logic exists, otherwise there will be a hash miss in emit_reverseport,
722                       --and DIO won't be able to get the model def.
723 
724                       BEGIN
725 
726                           SELECT devl_project_id INTO l_model_id
727                             FROM cz_ps_nodes
728                            WHERE deleted_flag = '0'
729                              AND ps_node_id = l_psn_reverseportid ( i );
730 
731                       EXCEPTION
732                          WHEN OTHERS THEN
733 
734                             --#<should never happen>
735                             report_and_raise_error (
736                                 p_message => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SE_REVCONNMODELNOTFOUND,
737                                     'MODEL_NAME',
738                                     CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH ( l_psn_reverseportid ( i ))),
739                                 p_run_id => x_run_id,
740                                 p_model_id => l_psn_reverseportid ( i )
741                             );
742 
743                       END;
744 
745                       read_model_data ( l_model_id );
746 
747                    END IF;
748                END IF;
749 
750                IF ( l_psn_referenceid ( i ) IS NOT NULL AND ( NOT h_devlid_modelvisited.EXISTS ( TO_CHAR ( l_psn_referenceid ( i ))))) THEN
751 
752                   read_model_data ( l_psn_referenceid ( i ));
753 
754                END IF;
755            END IF;
756 
757            IF ( l_psn_parentid ( i ) IS NOT NULL ) THEN
758 
759               --Calculate number of children for each parent. May be useful for setting fields like maximum_selected.
760 
761               l_parent_id  := TO_CHAR ( l_psn_parentid ( i ));
762               h_psnid_numberofchildren ( l_parent_id  ) := h_psnid_numberofchildren ( l_parent_id  ) + 1;
763 
764               --This table is useful when we need to collect all children of a parent across the whole
765               --structure.
766 
767               h_psnid_lastchildindex ( l_parent_id ) := h_psnid_backindex ( l_node_id );
768 
769            END IF;
770         END LOOP;
771 
772         --After the model structure is read we append a 'port' section at the end containing all the
773         --references and connectors in the structure, for which port variables will be created. The
774         --section is enclosed in 'beginport'/'endport' tokens and contains only the values that are
775         --required for creating port variables - this determined what arrays we populate below. For
776         --example, initial_value is not used for port variables, and we don't populate the array.
777 
778         --Components with defined reverse port are also here (one from each pair, another one is in
779         --the def file).
780 
781         --This section is REQUIRED even if it is empty - we always create all files of all possible
782         --types as a solution to the problem described in #<logic files handling>.
783 
784         set_token ('beginport');
785 
786         FOR i IN 1..l_port_table.COUNT LOOP
787 
788            l_index := l_port_table ( i );
789 
790            t_psn_psnodeid ( v_index ) := l_psn_psnodeid ( l_index );
791            t_psn_persistentnodeid ( v_index ) := l_psn_persistentnodeid ( l_index );
792            t_psn_parentid ( v_index ) := l_psn_parentid ( l_index );
793            t_psn_psnodetype ( v_index ) := l_psn_psnodetype ( l_index );
794            t_psn_referenceid ( v_index ) := l_psn_referenceid ( l_index );
795            t_psn_reverseportid ( v_index ) := l_psn_reverseportid ( l_index );
796            t_psn_devlprojectid ( v_index ) := l_psn_devlprojectid ( l_index );
797            t_psn_name ( v_index ) := l_psn_name ( l_index );
798            t_psn_minimum ( v_index ) := l_psn_minimum ( l_index );
799            t_psn_maximum ( v_index ) := l_psn_maximum ( l_index );
800            t_psn_virtualflag ( v_index ) := l_psn_virtualflag ( l_index );
801            t_psn_instantiableflag ( v_index ) := l_psn_instantiableflag ( l_index );
802            t_psn_bomrequiredflag ( v_index ) := l_psn_bomrequiredflag ( l_index );
803            t_psn_minimumselected( v_index ) := l_psn_minimumselected( l_index );
804            t_psn_maximumselected( v_index ) := l_psn_maximumselected( l_index );
805            t_psn_initialnumvalue( v_index ) := l_psn_initialnumvalue( l_index );
806            t_psn_effectivefrom( v_index ) := l_psn_effectivefrom( l_index );
807            t_psn_effectiveuntil( v_index ) := l_psn_effectiveuntil( l_index );
808            t_psn_effectiveusagemask( v_index ) := l_psn_effectiveusagemask( l_index );
809            t_psn_detailedtype ( v_index ) := l_psn_detailedtype ( l_index );
810 
811            v_index := v_index + 1;
812 
813         END LOOP;
814 
815         set_token ('endport');
816 
817         --Now append the 'rule' section which contains all ports on which we need to call setReversePort.
818         --For each of them, the call will be generated in the rule logic file. Note, that this section is
819         --REQUIRED even if there is no reverse ports and it is empty.
820 
821         set_token ('beginrule');
822 
823         FOR i IN 1..l_reverseport_table.COUNT LOOP
824 
825            l_index := l_reverseport_table ( i );
826 
827            t_psn_psnodeid ( v_index ) := l_psn_psnodeid ( l_index );
828            t_psn_persistentnodeid ( v_index ) := l_psn_persistentnodeid ( l_index );
829            t_psn_reverseportid ( v_index ) := l_psn_reverseportid ( l_index );
830            t_psn_psnodetype ( v_index ) := l_psn_psnodetype ( l_index );
831 
832            v_index := v_index + 1;
833 
834         END LOOP;
835 
836         set_token ('endrule');
837         set_token ('endstructure');
838 
839      END IF; --> l_psn_psnodeid.COUNT > 0
840   END read_model_data;
841 ---------------------------------------------------------------------------------------
842   -- Scope: compile_logic_
843   PROCEDURE compile_logic_file ( p_component_id IN NUMBER
844                                , p_type IN PLS_INTEGER
845                                , p_model_path IN VARCHAR2 DEFAULT NULL
846                                ) IS
847 
848    h_StringConstantHash       type_data_hashtable;
849    h_IntegerConstantHash      type_data_hashtable;
850    h_LongConstantHash         type_data_hashtable;
851    h_MaskConstantHash         type_data_hashtable;
852    h_DoubleConstantHash       type_data_hashtable;
853    h_MethodDescriptorHash     type_integer_table;
854 
855    h_LocalVariableHash        type_data_hashtable;
856    h_LocalVariableBackPtr     type_varchar4000_table;
857    h_RegisterHash             type_data_hashtable;
858 
859    l_var_min                  NUMBER;
860    l_var_max                  NUMBER;
861    l_var_count                NUMBER;
862    l_option_count             PLS_INTEGER;
863    l_feature_idx              PLS_INTEGER;
864    l_reverseportcount         PLS_INTEGER;
865 
866    l_begin_date               DATE;
867    l_end_date                 DATE;
868    l_model_path               VARCHAR2(4000);
869 ---------------------------------------------------------------------------------------
870 -------------------------- LOGIC FILE IMPLEMENTATION ----------------------------------
871 ---------------------------------------------------------------------------------------
872    pool_ptr                   PLS_INTEGER;
873    code_ptr                   PLS_INTEGER;
874    localvariable_ptr          PLS_INTEGER;
875    register_ptr               PLS_INTEGER;
876 
877    this_segment_nbr           NUMBER;
878    this_file_id               NUMBER;
879 
880    segment_nbr_svp            PLS_INTEGER;
881    code_ptr_svp               PLS_INTEGER;
882    pool_ptr_svp               PLS_INTEGER;
883 
884    h_StringConstantHash_svp   type_data_hashtable;
885    h_IntegerConstantHash_svp  type_data_hashtable;
886    h_LongConstantHash_svp     type_data_hashtable;
887    h_MaskConstantHash_svp     type_data_hashtable;
888    h_DoubleConstantHash_svp   type_data_hashtable;
889    h_MethodDescriptorHash_svp type_integer_table;
890 
891    h_LocalVariableHash_svp    type_data_hashtable;
892    h_RegisterHash_svp         type_data_hashtable;
893 
894    ConstantPool               BLOB;
895    CodeMemory                 BLOB;
896 
897    CodeMemory_buffer          VARCHAR2(32767 BYTE);
898    code_buffer_ptr            PLS_INTEGER;
899 
900    ConstantPool_buffer        VARCHAR2(32767 BYTE);
901    pool_buffer_ptr            PLS_INTEGER;
902 ---------------------------------------------------------------------------------------
903    -- Scope: compile_logic_file
904    PROCEDURE flush_constant_pool IS
905 
906      l_raw   RAW(32767) := HEXTORAW ( ConstantPool_buffer );
907      l_len   BINARY_INTEGER := UTL_RAW.LENGTH ( l_raw );
908 
909    BEGIN
910 
911      IF ( l_len > 0 ) THEN
912 
913         DBMS_LOB.WRITEAPPEND ( ConstantPool, l_len, l_raw );
914 
915      END IF;
916    END flush_constant_pool;
917 ---------------------------------------------------------------------------------------
918    -- Scope: compile_logic_file
919    PROCEDURE flush_code_memory IS
920 
921      l_raw   RAW(32767) := HEXTORAW ( CodeMemory_buffer );
922      l_len   BINARY_INTEGER := UTL_RAW.LENGTH ( l_raw );
923 
924    BEGIN
925 
926      IF ( l_len > 0 ) THEN
927 
928         DBMS_LOB.WRITEAPPEND ( CodeMemory, l_len, l_raw );
929 
930      END IF;
931    END flush_code_memory;
932 ---------------------------------------------------------------------------------------
933    -- Scope: compile_logic_file
934    PROCEDURE init_logic_file IS
935    BEGIN
936 
937      DBMS_LOB.CREATETEMPORARY ( ConstantPool, TRUE );
938      DBMS_LOB.CREATETEMPORARY ( CodeMemory, TRUE );
939 
940      CodeMemory_buffer := NULL;
941      code_buffer_ptr := 0;
942 
943      ConstantPool_buffer := NULL;
944      pool_buffer_ptr := 0;
945 
946      pool_ptr := 0;
947      code_ptr := 0;
948      this_segment_nbr := 1;
949 
950      localvariable_ptr := 0;
951      register_ptr := 0;
952 
953    END init_logic_file;
954 ---------------------------------------------------------------------------------------
955    -- Scope: compile_logic_file
956    PROCEDURE next_logic_segment IS
957    BEGIN
958 
959      DBMS_LOB.TRIM ( ConstantPool, 0 );
960      DBMS_LOB.TRIM ( CodeMemory, 0 );
961 
962      CodeMemory_buffer := NULL;
963      code_buffer_ptr := 0;
964 
965      ConstantPool_buffer := NULL;
966      pool_buffer_ptr := 0;
967 
968      pool_ptr := 0;
969      code_ptr := 0;
970      this_segment_nbr := this_segment_nbr + 1;
971 
972      h_StringConstantHash.DELETE;
973      h_IntegerConstantHash.DELETE;
974      h_LongConstantHash.DELETE;
975      h_MaskConstantHash.DELETE;
976      h_DoubleConstantHash.DELETE;
977      h_MethodDescriptorHash.DELETE;
978 
979    END next_logic_segment;
980 ---------------------------------------------------------------------------------------
981    -- Scope: compile_logic_file
982    PROCEDURE spool_logic_file IS
983 
984      l_file_id  NUMBER;
985      l_loc      BLOB;
986 
987    BEGIN
988 
989      flush_constant_pool ();
990      flush_code_memory ();
991 
992      IF ( pool_ptr + code_ptr > 0 ) THEN
993 
994         DBMS_LOB.CREATETEMPORARY ( l_loc, TRUE );
995 
996         IF ( pool_ptr > 0 ) THEN DBMS_LOB.APPEND ( l_loc, ConstantPool ); END IF;
997         IF ( code_ptr > 0 ) THEN DBMS_LOB.APPEND ( l_loc, CodeMemory ); END IF;
998 
999         DBMS_LOB.WRITEAPPEND ( l_loc, 4, cz_fce_compile_utils.integer_raw ( pool_ptr ));
1000         DBMS_LOB.WRITEAPPEND ( l_loc, 4, const_file_signature );
1001 
1002         IF ( this_segment_nbr = 1 ) THEN
1003 
1004            SELECT cz_fce_files_s.NEXTVAL INTO this_file_id FROM DUAL;
1005 
1006            --This does not delete a logic file if there is no such type in the current generation.
1007            --For example, if an only port has been removed from the model, there will be no port
1008            --file in this generation, so the current port file will not be deleted.
1009 
1010            --#<problem>
1011            --Need a better handling of this problem. For now we will always create files of all
1012            --possible types even if they are empty. We do that for rule files anyway.
1013 
1014            UPDATE cz_fce_files SET deleted_flag = '1'
1015             WHERE component_id = p_component_id
1016               AND fce_file_type = p_type;
1017 
1018         ELSE
1019 
1020            --Need that in case we are restoring to a savepoint in the previous segment.
1021 
1022            DELETE FROM cz_fce_files
1023             WHERE component_id = p_component_id
1024               AND fce_file_type = p_type
1025               AND segment_nbr = this_segment_nbr;
1026 
1027         END IF;
1028 
1029         INSERT INTO cz_fce_files ( FCE_FILE_ID
1030                                  , FCE_FILE_TYPE
1031                                  , COMPONENT_ID
1032                                  , SEGMENT_NBR
1033                                  , FCE_FILE
1034                                  , DELETED_FLAG
1035                                  , DEBUG_FLAG
1036                                  )
1037                           VALUES ( this_file_id
1038                                  , p_type
1039                                  , p_component_id
1040                                  , this_segment_nbr
1041                                  , l_loc
1042                                  , '0'
1043                                  , TO_CHAR ( p_debug_mode )
1044                                  );
1045      END IF;
1046    END spool_logic_file;
1047 ---------------------------------------------------------------------------------------
1048    -- Scope: compile_logic_file
1049    PROCEDURE emit_code ( p_code IN RAW ) IS
1050 
1051      l_code      VARCHAR2(128 BYTE) := RAWTOHEX ( p_code );
1052      l_len       BINARY_INTEGER := LENGTHB ( l_code );
1053 
1054    BEGIN
1055 
1056       code_buffer_ptr := code_buffer_ptr + l_len;
1057       code_ptr := code_ptr + UTL_RAW.LENGTH ( p_code );
1058 
1059       IF ( code_buffer_ptr >= const_codememory_buffersize ) THEN
1060 
1061         flush_code_memory ();
1062 
1063         CodeMemory_buffer := NULL;
1064         code_buffer_ptr := l_len;
1065 
1066       END IF;
1067 
1068       CodeMemory_buffer := CodeMemory_buffer || l_code;
1069 
1070    END emit_code;
1071 ---------------------------------------------------------------------------------------
1072    -- Scope: compile_logic_file
1073    FUNCTION emit_data ( p_data IN RAW ) RETURN PLS_INTEGER IS
1074 
1075      l_pool_ptr  PLS_INTEGER;
1076      l_len       BINARY_INTEGER := UTL_RAW.LENGTH ( p_data );
1077 
1078      l_data      VARCHAR2(32767 BYTE) := RAWTOHEX ( p_data );
1079      l_data_len  BINARY_INTEGER := LENGTHB ( l_data );
1080 
1081    BEGIN
1082 
1083       IF ( pool_ptr >= const_constantpool_maxsize ) THEN
1084 
1085           --Here the switch to the next logic file will be handled. The switch will occur
1086           --when the constant pool overflown.
1087 
1088           emit_code ( h_inst ('ret'));
1089           spool_logic_file ();
1090 
1091           next_logic_segment ();
1092 
1093       END IF;
1094 
1095       IF ( l_data_len >= const_constantpool_buffersize ) THEN
1096 
1097         flush_constant_pool ();
1098 
1099         DBMS_LOB.WRITEAPPEND ( ConstantPool, l_len, p_data );
1100 
1101         ConstantPool_buffer := NULL;
1102         pool_buffer_ptr := 0;
1103 
1104       ELSE
1105 
1106          pool_buffer_ptr := pool_buffer_ptr + l_data_len;
1107 
1108          IF ( pool_buffer_ptr >= const_constantpool_buffersize ) THEN
1109 
1110            flush_constant_pool ();
1111 
1112            ConstantPool_buffer := NULL;
1113            pool_buffer_ptr := l_data_len;
1114 
1115          END IF;
1116 
1117          ConstantPool_buffer := ConstantPool_buffer || l_data;
1118 
1119       END IF;
1120 
1121       l_pool_ptr := pool_ptr;
1122       pool_ptr := pool_ptr + l_len;
1123 
1124       RETURN l_pool_ptr;
1125 
1126    END emit_data;
1127 ---------------------------------------------------------------------------------------
1128    --Savepoints allow to delete partially generated byte-code when generation fails.
1129    -- Scope: compile_logic_file
1130    PROCEDURE set_savepoint IS
1131    BEGIN
1132 
1133       segment_nbr_svp := this_segment_nbr;
1134 
1135       code_ptr_svp := code_ptr;
1136       pool_ptr_svp := pool_ptr;
1137 
1138       h_StringConstantHash_svp := h_StringConstantHash;
1139       h_IntegerConstantHash_svp := h_IntegerConstantHash;
1140       h_LongConstantHash_svp := h_LongConstantHash;
1141       h_MaskConstantHash_svp := h_MaskConstantHash;
1142       h_DoubleConstantHash_svp := h_DoubleConstantHash;
1143       h_MethodDescriptorHash_svp := h_MethodDescriptorHash;
1144 
1145       h_LocalVariableHash_svp := h_LocalVariableHash;
1146       h_RegisterHash_svp := h_RegisterHash;
1147 
1148    END set_savepoint;
1149 ---------------------------------------------------------------------------------------
1150    -- Scope: compile_logic_file
1151    PROCEDURE restore_savepoint IS
1152 
1153       l_size       PLS_INTEGER;
1154       l_tail       PLS_INTEGER;
1155 
1156       l_fce_file   BLOB;
1157 
1158    BEGIN
1159 
1160       IF ( segment_nbr_svp < this_segment_nbr ) THEN
1161 
1162          --This is a situation when the savepoint is in the previous segment, which has
1163          --already been saved to the database, for example segment switching occured in
1164          --in the middle of a rule generation, and this rule has to be rolled back. The
1165          --previous segment nees to be restored in memory from the database.
1166 
1167          DBMS_LOB.TRIM ( ConstantPool, 0 );
1168          DBMS_LOB.TRIM ( CodeMemory, 0 );
1169 
1170          SELECT fce_file INTO l_fce_file FROM cz_fce_files
1171           WHERE deleted_flag = '0'
1172             AND component_id = p_component_id
1173             AND fce_file_type = p_type
1174             AND segment_nbr = segment_nbr_svp;
1175 
1176          --According to the logic file format, second four bytes from the end store the
1177          --size of the Constant Pool.
1178 
1179          l_size := UTL_RAW.CAST_TO_BINARY_INTEGER ( DBMS_LOB.SUBSTR ( l_fce_file, 4, DBMS_LOB.GETLENGTH ( l_fce_file ) - 7 ));
1180          l_tail := DBMS_LOB.GETLENGTH ( l_fce_file ) - 8 - l_size;
1181 
1182          IF ( l_size > 0 ) THEN ConstantPool := DBMS_LOB.SUBSTR ( l_fce_file, l_size, 1 ); END IF;
1183          IF ( l_tail > 0 ) THEN CodeMemory := DBMS_LOB.SUBSTR ( l_fce_file, l_tail, l_size + 1 ); END IF;
1184 
1185          this_segment_nbr := segment_nbr_svp;
1186 
1187       ELSE
1188 
1189          flush_constant_pool ();
1190          flush_code_memory ();
1191 
1192       END IF;
1193 
1194       code_ptr := code_ptr_svp;
1195       pool_ptr := pool_ptr_svp;
1196 
1197       DBMS_LOB.TRIM ( CodeMemory, code_ptr_svp );
1198       DBMS_LOB.TRIM ( ConstantPool, pool_ptr_svp );
1199 
1200       CodeMemory_buffer := NULL;
1201       code_buffer_ptr := 0;
1202 
1203       ConstantPool_buffer := NULL;
1204       pool_buffer_ptr := 0;
1205 
1206       h_StringConstantHash := h_StringConstantHash_svp;
1207       h_IntegerConstantHash := h_IntegerConstantHash_svp;
1208       h_LongConstantHash := h_LongConstantHash_svp;
1209       h_MaskConstantHash := h_MaskConstantHash_svp;
1210       h_DoubleConstantHash := h_DoubleConstantHash_svp;
1211       h_MethodDescriptorHash := h_MethodDescriptorHash_svp;
1212 
1213       h_LocalVariableHash := h_LocalVariableHash_svp;
1214       h_RegisterHash := h_RegisterHash_svp;
1215 
1216    END restore_savepoint;
1217 ---------------------------------------------------------------------------------------
1218 -------------------------- LOGIC FILE IMPLEMENTATION ----------------------------------
1219 ---------------------------------------------------------------------------------------
1220    -- Scope: compile_logic_file
1221    PROCEDURE emit_ldc ( p_ptr IN PLS_INTEGER ) IS
1222    BEGIN
1223 
1224       IF ( cz_fce_compile_utils.assert_unsigned_byte ( p_ptr )) THEN
1225 
1226          emit_code ( h_inst ('ldc') || cz_fce_compile_utils.unsigned_byte ( p_ptr ));
1227 
1228       ELSIF ( cz_fce_compile_utils.assert_unsigned_word ( p_ptr )) THEN
1229 
1230          emit_code ( h_inst ('ldc_w') || cz_fce_compile_utils.unsigned_word ( p_ptr ));
1231 
1232       ELSE
1233 
1234          report_and_raise_sys_error(
1235             p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_POINTER_TOO_LONG),
1236             p_run_id => x_run_id,
1237             p_model_id => p_component_id
1238          );
1239 
1240       END IF;
1241    END emit_ldc;
1242 ---------------------------------------------------------------------------------------
1243    -- Scope: compile_logic_file
1244    PROCEDURE emit_iconst ( p_int IN NUMBER ) IS
1245    BEGIN
1246 
1247       IF ( p_int = ( -1 )) THEN
1248 
1249          emit_code ( h_inst ('iconst_m1'));
1250 
1251       ELSE
1252 
1253          emit_code ( h_inst ('iconst_' || TO_CHAR ( p_int )));
1254 
1255       END IF;
1256    END emit_iconst;
1257 ---------------------------------------------------------------------------------------
1258    -- Scope: compile_logic_file
1259    PROCEDURE emit_dup IS
1260    BEGIN
1261 
1262       emit_code ( h_inst ('dup'));
1263 
1264    END emit_dup;
1265 ---------------------------------------------------------------------------------------
1266    -- Scope: compile_logic_file
1267    PROCEDURE emit_swap IS
1268    BEGIN
1269 
1270       emit_code ( h_inst ('swap'));
1271 
1272    END emit_swap;
1273 ---------------------------------------------------------------------------------------
1274    -- Scope: compile_logic_file
1275    FUNCTION emit_string_constant ( p_string IN VARCHAR2 ) RETURN PLS_INTEGER IS
1276 
1277      l_pool_ptr  PLS_INTEGER;
1278 
1279    BEGIN
1280 
1281       IF (NOT h_StringConstantHash.EXISTS( p_string )) THEN
1282 
1283          --This uses the format of string constant entry in the constant pool. If the format changes,
1284          --this will have to change.
1285          --#<constant pool format>
1286 
1287          IF ( cz_fce_compile_utils.assert_unsigned_word ( LENGTHB ( p_string ))) THEN
1288 
1289             l_pool_ptr := emit_data ( const_string_tag || cz_fce_compile_utils.unsigned_word ( LENGTHB ( p_string )) ||
1290                           UTL_RAW.CAST_TO_RAW ( p_string ));
1291             h_StringConstantHash( p_string ) := l_pool_ptr;
1292 
1293          ELSE
1294 
1295             report_and_raise_sys_error(
1296                 p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_STRING_TOO_LONG),
1297                 p_run_id => x_run_id,
1298                 p_model_id => p_component_id
1299              );
1300 
1301          END IF;
1302 
1303       ELSE
1304 
1305          l_pool_ptr := h_StringConstantHash( p_string );
1306 
1307       END IF;
1308       RETURN l_pool_ptr;
1309 
1310    END emit_string_constant;
1311 ---------------------------------------------------------------------------------------
1312    -- Scope: compile_logic_file
1313    FUNCTION emit_integer_constant ( p_int IN NUMBER ) RETURN PLS_INTEGER IS
1314 
1315      l_key  VARCHAR2(4000) := TO_CHAR (p_int);
1316      l_ptr  PLS_INTEGER;
1317 
1318    BEGIN
1319 
1320       IF (NOT h_IntegerConstantHash.EXISTS ( l_key )) THEN
1321 
1322          --#<constant pool format>
1323 
1324          l_ptr := emit_data ( const_integer_tag || cz_fce_compile_utils.integer_raw ( p_int ));
1325          h_IntegerConstantHash( l_key ) := l_ptr;
1326 
1327       ELSE
1328 
1329          l_ptr := h_IntegerConstantHash ( l_key );
1330 
1331       END IF;
1332       RETURN l_ptr;
1333    END emit_integer_constant;
1334 ---------------------------------------------------------------------------------------
1335    -- Scope: compile_logic_file
1336    FUNCTION emit_long_constant ( p_int IN NUMBER ) RETURN PLS_INTEGER IS
1337 
1338      l_key  VARCHAR2(4000) := TO_CHAR ( p_int );
1339      l_ptr  PLS_INTEGER;
1340 
1341    BEGIN
1342 
1343       IF (NOT h_LongConstantHash.EXISTS ( l_key )) THEN
1344 
1345          --#<constant pool format>
1346 
1347          l_ptr := emit_data ( const_long_tag || cz_fce_compile_utils.long_raw ( p_int ));
1348          h_LongConstantHash( l_key ) := l_ptr;
1349 
1350       ELSE
1351 
1352          l_ptr := h_LongConstantHash ( l_key );
1353 
1354       END IF;
1355       RETURN l_ptr;
1356    END emit_long_constant;
1357 ---------------------------------------------------------------------------------------
1358    -- Scope: compile_logic_file
1359    --This functions emits a string of 16 hex characters as a long.
1360    --Example: effective_usage_mask
1361    FUNCTION emit_mask_constant ( p_mask IN VARCHAR2 ) RETURN PLS_INTEGER IS
1362 
1363      l_ptr  PLS_INTEGER;
1364 
1365    BEGIN
1366 
1367       IF (NOT h_MaskConstantHash.EXISTS ( p_mask )) THEN
1368 
1369           --#<constant pool format> long constant.
1370 
1371          l_ptr := emit_data ( const_long_tag || HEXTORAW ( p_mask ));
1372          h_MaskConstantHash( p_mask ) := l_ptr;
1373 
1374       ELSE
1375 
1376          l_ptr := h_MaskConstantHash ( p_mask );
1377 
1378       END IF;
1379       RETURN l_ptr;
1380    END emit_mask_constant;
1381 ---------------------------------------------------------------------------------------
1382    --Scope: compile_logic_file
1383    --This functions emits a date in Java's long representation.
1384    --Example: effective_from, effective_until
1385    FUNCTION emit_date_constant ( p_date IN DATE ) RETURN PLS_INTEGER IS
1386 
1387      l_num  NUMBER := ( p_date - const_java_epoch_begin ) * 86400000;
1388      l_key  VARCHAR2(4000) := TO_CHAR ( l_num );
1389      l_ptr  PLS_INTEGER;
1390 
1391    BEGIN
1392 
1393       IF (NOT h_LongConstantHash.EXISTS ( l_key )) THEN
1394 
1395          --#<constant pool format>
1396 
1397          l_ptr := emit_data ( const_date_tag || cz_fce_compile_utils.long_raw ( l_num ));
1398          h_LongConstantHash ( l_key ) := l_ptr;
1399 
1400       ELSE
1401 
1402          l_ptr := h_LongConstantHash ( l_key );
1403 
1404       END IF;
1405       RETURN l_ptr;
1406    END emit_date_constant;
1407 ---------------------------------------------------------------------------------------
1408    -- Scope: compile_logic_file
1409    FUNCTION emit_double_constant ( p_number IN NUMBER ) RETURN PLS_INTEGER IS
1410 
1411      l_ptr  PLS_INTEGER;
1412      l_key  VARCHAR2(4000) := TO_CHAR ( p_number );
1413 
1414    BEGIN
1415 
1416       IF (NOT h_DoubleConstantHash.EXISTS ( l_key )) THEN
1417 
1418          --#<constant pool format>
1419 
1420          l_ptr := emit_data ( const_double_tag || cz_fce_compile_utils.double_raw ( p_number ));
1421          h_DoubleConstantHash ( l_key ) := l_ptr;
1422 
1423       ELSE
1424 
1425          l_ptr := h_DoubleConstantHash ( l_key );
1426 
1427       END IF;
1428       RETURN l_ptr;
1429    END emit_double_constant;
1430 ---------------------------------------------------------------------------------------
1431    -- Scope: compile_logic_file
1432    PROCEDURE push_string_constant ( p_string IN VARCHAR2 ) IS
1433    BEGIN
1434 
1435         emit_ldc ( emit_string_constant ( p_string ));
1436 
1437    END push_string_constant;
1438 ---------------------------------------------------------------------------------------
1439    -- Scope: compile_logic_file
1440    PROCEDURE push_double_constant ( p_number IN NUMBER ) IS
1441    BEGIN
1442 
1443       emit_ldc ( emit_double_constant ( p_number ));
1444 
1445    END push_double_constant;
1446 ---------------------------------------------------------------------------------------
1447    -- Scope: compile_logic_file
1448    PROCEDURE push_mask_constant ( p_mask IN VARCHAR2 ) IS
1449    BEGIN
1450 
1451       emit_ldc ( emit_mask_constant ( p_mask ));
1452 
1453    END push_mask_constant;
1454 ---------------------------------------------------------------------------------------
1455    -- Scope: compile_logic_file
1456    PROCEDURE push_date_constant ( p_date IN DATE ) IS
1457    BEGIN
1458 
1459       emit_ldc ( emit_date_constant ( p_date ));
1460 
1461    END push_date_constant;
1462 ---------------------------------------------------------------------------------------
1463    -- Scope: compile_logic_file
1464    --This procedure is different from the push_long_constant in that it does not go
1465    --beyond integer. This is useful when we need to be sure that the number is not
1466    --long, for example when pushing an array size or integer parameters.
1467 
1468    PROCEDURE push_integer_constant ( p_int IN PLS_INTEGER ) IS
1469    BEGIN
1470 
1471       IF ( cz_fce_compile_utils.assert_iconst ( p_int )) THEN
1472 
1473          emit_iconst ( p_int );
1474 
1475       ELSIF ( cz_fce_compile_utils.assert_byte ( p_int )) THEN
1476 
1477          emit_code ( h_inst ('bipush') || cz_fce_compile_utils.byte ( p_int ));
1478 
1479       ELSIF ( cz_fce_compile_utils.assert_word ( p_int )) THEN
1480 
1481          emit_code ( h_inst ('sipush') || cz_fce_compile_utils.word ( p_int ));
1482 
1483       ELSIF ( cz_fce_compile_utils.assert_integer ( p_int )) THEN
1484 
1485          emit_ldc ( emit_integer_constant ( p_int ));
1486 
1487       ELSE
1488 
1489          report_and_raise_sys_error(
1490             p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_INTEGER_TOO_LONG, 'VALUE', TO_CHAR ( p_int )),
1491             p_run_id => x_run_id,
1492             p_model_id => p_component_id
1493          );
1494 
1495       END IF;
1496    END push_integer_constant;
1497 ---------------------------------------------------------------------------------------
1498    -- Scope: compile_logic_file
1499    PROCEDURE push_long_constant ( p_int IN NUMBER ) IS
1500 
1501       l_ptr  PLS_INTEGER;
1502 
1503    BEGIN
1504 
1505       IF ( cz_fce_compile_utils.assert_integer ( p_int )) THEN
1506 
1507          push_integer_constant ( p_int );
1508 
1509       ELSIF ( cz_fce_compile_utils.assert_long ( p_int )) THEN
1510 
1511          emit_ldc ( emit_long_constant ( p_int ));
1512 
1513       ELSE
1514 
1515          report_and_raise_sys_error(
1516             p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_LONG_TOO_LONG, 'VALUE', TO_CHAR ( p_int )),
1517             p_run_id => x_run_id,
1518             p_model_id => p_component_id
1519          );
1520 
1521       END IF;
1522    END push_long_constant;
1523 ---------------------------------------------------------------------------------------
1524    -- Scope: compile_logic_file
1525    --This procedure tries to push the decimal in the most economical way, first as an
1526    --integer, if that fails as a 4-byte float and if that fails - as a 8-byte double.
1527    --If there are any problems in Java with implicit conversions, we may need to give
1528    --up using float constants at all, and this procedure will just push double.
1529 
1530    --Bug #6730258 shows, that we have to give up trying to store decimal constants as
1531    --floats. All procedures working with float numbers are removed from this package.
1532    --They can also be removed from cz_fce_compile_utils and ConstantPool class.
1533 
1534    PROCEDURE push_decimal_constant ( p_number IN NUMBER ) IS
1535    BEGIN
1536 
1537       IF ( ROUND ( p_number ) = p_number AND cz_fce_compile_utils.assert_long ( p_number )) THEN
1538 
1539          push_long_constant ( p_number );
1540 
1541       ELSE
1542 
1543          push_double_constant ( p_number );
1544 
1545       END IF;
1546    END push_decimal_constant;
1547 ---------------------------------------------------------------------------------------
1548    -- Scope: compile_logic_file
1549    PROCEDURE emit_pop ( p_elements IN PLS_INTEGER ) IS
1550    BEGIN
1551 
1552       IF ( p_elements = 0 ) THEN
1553 
1554          RETURN;
1555 
1556       ELSIF ( p_elements = 1 ) THEN
1557 
1558          emit_code( h_inst('pop'));
1559 
1560       ELSE
1561 
1562          push_integer_constant ( p_elements );
1563          emit_code( h_inst('mpop'));
1564 
1565       END IF;
1566    END emit_pop;
1567 ---------------------------------------------------------------------------------------
1568    -- Scope: compile_logic_file
1569    FUNCTION emit_method_descriptor ( p_ptr IN PLS_INTEGER ) RETURN PLS_INTEGER IS
1570 
1571      l_ptr  PLS_INTEGER;
1572 
1573    BEGIN
1574 
1575       IF (NOT h_MethodDescriptorHash.EXISTS( p_ptr )) THEN
1576 
1577          IF ( cz_fce_compile_utils.assert_unsigned_byte( p_ptr )) THEN
1578 
1579             l_ptr := emit_data(const_method_tag || cz_fce_compile_utils.unsigned_byte( p_ptr ));
1580             h_MethodDescriptorHash( p_ptr ) := l_ptr;
1581 
1582          ELSE
1583 
1584             report_and_raise_sys_error(
1585                 p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_METHODIX_OUTOFRANGE, 'VALUE', TO_CHAR ( p_ptr )),
1586                 p_run_id => x_run_id,
1587                 p_model_id => p_component_id
1588              );
1589 
1590          END IF;
1591 
1592       ELSE
1593 
1594          l_ptr := h_MethodDescriptorHash( p_ptr );
1595 
1596       END IF;
1597       RETURN l_ptr;
1598    END emit_method_descriptor;
1599 ---------------------------------------------------------------------------------------
1600    -- Scope: compile_logic_file
1601    PROCEDURE emit_invokestatic ( p_signature IN VARCHAR2 ) IS
1602    BEGIN
1603 
1604       emit_code(h_inst('invokestatic') ||
1605            cz_fce_compile_utils.unsigned_word ( emit_method_descriptor ( h_methoddescriptors ( p_signature ))));
1606 
1607    END emit_invokestatic;
1608 ---------------------------------------------------------------------------------------
1609    -- Scope: compile_logic_file
1610    PROCEDURE emit_invokevirtual ( p_signature IN VARCHAR2 ) IS
1611    BEGIN
1612 
1613       emit_code(h_inst('invokevirtual') ||
1614            cz_fce_compile_utils.unsigned_word ( emit_method_descriptor ( h_methoddescriptors ( p_signature ))));
1615 
1616    END emit_invokevirtual;
1617 ---------------------------------------------------------------------------------------
1618    -- Scope: compile_logic_file
1619    PROCEDURE emit_regop ( p_ptr IN PLS_INTEGER, p_op IN VARCHAR2 ) IS
1620    BEGIN
1621 
1622       IF ( p_op NOT IN ( 'astore', 'copyto', 'aload' )) THEN
1623 
1624           report_and_raise_sys_error(
1625             p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_UNKNOWN_OPERATION, 'OPERATION', p_op),
1626             p_run_id => x_run_id,
1627             p_model_id => p_component_id
1628            );
1629 
1630       END IF;
1631 
1632       IF ( NOT cz_fce_compile_utils.assert_unsigned_byte ( p_ptr )) THEN
1633 
1634           report_and_raise_sys_error(
1635             p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_INVALID_ACCESS_VAR, 'OPERATION', p_op, 'VAR', TO_CHAR ( p_ptr )),
1636             p_run_id => x_run_id,
1637             p_model_id => p_component_id
1638            );
1639 
1640       END IF;
1641 
1642       IF ( p_ptr < 4 ) THEN
1643 
1644          emit_code ( h_inst ( p_op || '_' || TO_CHAR ( p_ptr )));
1645 
1646       ELSE
1647 
1648          emit_code ( h_inst ( p_op ) || cz_fce_compile_utils.unsigned_byte ( p_ptr ));
1649 
1650       END IF;
1651    END emit_regop;
1652 ---------------------------------------------------------------------------------------
1653    -- Scope: compile_logic_file
1654    PROCEDURE emit_regop_w ( p_ptr IN PLS_INTEGER, p_op IN VARCHAR2 ) IS
1655    BEGIN
1656 
1657       IF ( p_op NOT IN ( 'astore', 'copyto', 'aload' )) THEN
1658 
1659           report_and_raise_sys_error(
1660             p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_UNKNOWN_OPERATION, 'OPERATION', p_op || '_w'),
1661             p_run_id => x_run_id,
1662             p_model_id => p_component_id
1663            );
1664 
1665       END IF;
1666 
1667       IF ( NOT cz_fce_compile_utils.assert_unsigned_word ( p_ptr )) THEN
1668 
1669           report_and_raise_sys_error(
1670             p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_INVALID_ACCESS_VARW, 'OPERATION', p_op, 'VAR', TO_CHAR ( p_ptr )),
1671             p_run_id => x_run_id,
1672             p_model_id => p_component_id
1673            );
1674 
1675       END IF;
1676 
1677       emit_code ( h_inst ( p_op || '_w') || cz_fce_compile_utils.unsigned_word ( p_ptr ));
1678 
1679    END emit_regop_w;
1680 ---------------------------------------------------------------------------------------
1681    -- Scope: compile_logic_file
1682    PROCEDURE emit_boolean ( p_value IN VARCHAR2 ) IS
1683    BEGIN
1684 
1685       IF ( p_value = '0' ) THEN
1686 
1687          emit_code ( h_inst ('pushfalse'));
1688 
1689       ELSE
1690 
1691          emit_code ( h_inst ('pushtrue'));
1692 
1693       END IF;
1694    END emit_boolean;
1695 ---------------------------------------------------------------------------------------
1696    -- Scope: compile_logic_file
1697    PROCEDURE emit_constant ( p_int IN NUMBER ) IS
1698    BEGIN
1699 
1700       emit_code ( h_inst ('pushmath') || cz_fce_compile_utils.unsigned_byte ( p_int ));
1701 
1702    END emit_constant;
1703 ---------------------------------------------------------------------------------------
1704    PROCEDURE emit_comment ( p_string IN VARCHAR2 ) IS
1705    BEGIN
1706 
1707       emit_code ( h_inst ('comment') || cz_fce_compile_utils.unsigned_word ( emit_string_constant ( p_string )));
1708 
1709    END emit_comment;
1710 ---------------------------------------------------------------------------------------
1711    --The Interpreter has 2 hastore instructions:
1712    --hastore_0 stores in the internal hash #0;
1713    --hastore_1 stores in the internal hash #1.
1714    -- Scope: compile_logic_file
1715    PROCEDURE hastore_object ( p_id IN NUMBER, p_hash IN PLS_INTEGER ) IS
1716    BEGIN
1717 
1718       push_long_constant( p_id );
1719       emit_code ( h_inst ( 'hastore_' || TO_CHAR ( p_hash )));
1720 
1721    END hastore_object;
1722 ---------------------------------------------------------------------------------------
1723    --The Interpreter has 3 haload instructions, this procedure handles 2 of them:
1724    --haload_0 loads from the internal hash #0;
1725    --haload_1 loads from the internal hash #1;
1726    -- Scope: compile_logic_file
1727    PROCEDURE haload_object ( p_id IN NUMBER, p_hash IN PLS_INTEGER ) IS
1728    BEGIN
1729 
1730       push_long_constant ( p_id );
1731       emit_code (h_inst ( 'haload_' || TO_CHAR ( p_hash )));
1732 
1733    END haload_object;
1734 ---------------------------------------------------------------------------------------
1735    -- Scope: compile_logic_file
1736    PROCEDURE haload2_object ( p_ref_id IN NUMBER ) IS
1737    BEGIN
1738 
1739       push_long_constant( p_ref_id );
1740       emit_code ( h_inst ( 'haload_2'));
1741 
1742    END haload2_object;
1743 ---------------------------------------------------------------------------------------
1744    -- Scope: compile_logic_file
1745    FUNCTION allocate_local_variable RETURN PLS_INTEGER IS
1746 
1747      l_ptr  PLS_INTEGER := localvariable_ptr;
1748 
1749    BEGIN
1750 
1751       IF ( localvariable_ptr < const_max_localvariables ) THEN
1752 
1753          localvariable_ptr := localvariable_ptr + 1;
1754 
1755       ELSE
1756 
1757          --All local variables are allocated, select a local variables to use.
1758          --Algorithms, like 'least used' variable, can be implemented here.
1759 
1760          localvariable_ptr := 0;
1761          l_ptr := 0;
1762 
1763       END IF;
1764 
1765       --Important: if the allocated local variable was used to store an object
1766       --and now is being overloaded, we need to disassociate that object with
1767       --this local variable otherwise code may think that this object is still
1768       --stored in this variable.
1769 
1770       IF (h_LocalVariableBackPtr.EXISTS( l_ptr )) THEN
1771 
1772          h_LocalVariableHash.DELETE(h_LocalVariableBackPtr( l_ptr ));
1773 
1774       END IF;
1775 
1776       RETURN l_ptr;
1777    END allocate_local_variable;
1778 ---------------------------------------------------------------------------------------
1779    -- Scope: compile_logic_file
1780    FUNCTION local_variable_defined ( p_key IN VARCHAR ) RETURN BOOLEAN IS
1781    BEGIN
1782 
1783       RETURN h_LocalVariableHash.EXISTS( p_key );
1784 
1785    END local_variable_defined;
1786 ---------------------------------------------------------------------------------------
1787    -- Scope: compile_logic_file
1788    FUNCTION local_variable_index ( p_key IN VARCHAR2 ) RETURN PLS_INTEGER IS
1789 
1790      l_ptr  PLS_INTEGER;
1791 
1792    BEGIN
1793 
1794       --Note, that this implementation re-writes a local variable, if such variable has
1795       --already been allocated for the key. This is done in order to allow many-to-one
1796       --object-key relation, for example, several root expressions in the same rule can
1797       --be keyed by rule_id and stored in the same variable one after another.
1798 
1799       IF ( NOT local_variable_defined ( p_key )) THEN
1800 
1801          l_ptr := allocate_local_variable ();
1802          h_LocalVariableHash( p_key ) := l_ptr;
1803          h_LocalVariableBackPtr( l_ptr ) := p_key;
1804 
1805       ELSE
1806 
1807          l_ptr := h_LocalVariableHash ( p_key );
1808 
1809       END IF;
1810 
1811       RETURN l_ptr;
1812    END local_variable_index;
1813 ---------------------------------------------------------------------------------------
1814    -- Scope: compile_logic_file
1815    PROCEDURE astore_local_variable ( p_key IN VARCHAR2 ) IS
1816    BEGIN
1817 
1818       emit_regop ( local_variable_index ( p_key ), 'astore' );
1819 
1820    END astore_local_variable;
1821 ---------------------------------------------------------------------------------------
1822    -- Scope: compile_logic_file
1823    PROCEDURE copyto_local_variable ( p_id IN NUMBER ) IS
1824    BEGIN
1825 
1826       emit_regop ( local_variable_index ( TO_CHAR( p_id )), 'copyto' );
1827 
1828    END copyto_local_variable;
1829 ---------------------------------------------------------------------------------------
1830    -- Scope: compile_logic_file
1831    PROCEDURE copyto_local_variable ( p_key IN VARCHAR2 ) IS
1832    BEGIN
1833 
1834       emit_regop ( local_variable_index ( p_key ), 'copyto' );
1835 
1836    END copyto_local_variable;
1837 ---------------------------------------------------------------------------------------
1838    -- Scope: compile_logic_file
1839    PROCEDURE aload_local_variable ( p_key IN VARCHAR2 ) IS
1840    BEGIN
1841 
1842       IF ( NOT local_variable_defined ( p_key )) THEN
1843 
1844         --#<should never happen>
1845         report_and_raise_sys_error(
1846             p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_UNDEFINED_LOCAL_VAR, 'KEY', p_key),
1847             p_run_id => x_run_id,
1848             p_model_id => p_component_id
1849         );
1850 
1851       END IF;
1852 
1853       emit_regop ( h_LocalVariableHash ( p_key ), 'aload' );
1854 
1855    END aload_local_variable;
1856 ---------------------------------------------------------------------------------------
1857 ---------------------------------------------------------------------------------------
1858    -- Scope: compile_logic_file
1859    PROCEDURE free_registers IS
1860    BEGIN
1861 
1862        register_ptr := 0;
1863        h_RegisterHash.DELETE;
1864 
1865    END free_registers;
1866 ---------------------------------------------------------------------------------------
1867    -- Scope: compile_logic_file
1868    FUNCTION allocate_register RETURN PLS_INTEGER IS
1869 
1870      l_ptr  PLS_INTEGER := register_ptr;
1871 
1872    BEGIN
1873 
1874       IF ( register_ptr >= const_max_registers ) THEN
1875 
1876          report_and_raise_sys_error(
1877             p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_NO_MORE_REGISTERS),
1878             p_run_id => x_run_id,
1879             p_model_id => p_component_id
1880         );
1881       END IF;
1882 
1883       register_ptr := register_ptr + 1;
1884 
1885       RETURN l_ptr;
1886    END allocate_register;
1887 ---------------------------------------------------------------------------------------
1888    -- Scope: compile_logic_file
1889    FUNCTION register_defined ( p_key IN VARCHAR ) RETURN BOOLEAN IS
1890    BEGIN
1891 
1892       RETURN h_RegisterHash.EXISTS( p_key );
1893 
1894    END register_defined;
1895 ---------------------------------------------------------------------------------------
1896    -- Scope: compile_logic_file
1897    FUNCTION register_index ( p_key IN VARCHAR2 ) RETURN PLS_INTEGER IS
1898 
1899      l_ptr  PLS_INTEGER;
1900 
1901    BEGIN
1902 
1903       --Note, that this implementation re-writes a local variable, if such variable has
1904       --already been allocated for the key.
1905 
1906       IF ( NOT register_defined ( p_key )) THEN
1907 
1908          l_ptr := allocate_register ();
1909          h_RegisterHash( p_key ) := l_ptr;
1910 
1911       ELSE
1912 
1913          l_ptr := h_RegisterHash ( p_key );
1914 
1915       END IF;
1916 
1917       RETURN l_ptr;
1918    END register_index;
1919 ---------------------------------------------------------------------------------------
1920    -- Scope: compile_logic_file
1921    PROCEDURE astore_register ( p_key IN VARCHAR2 ) IS
1922    BEGIN
1923 
1924       emit_regop_w ( register_index ( p_key ), 'astore' );
1925 
1926    END astore_register;
1927 ---------------------------------------------------------------------------------------
1928    -- Scope: compile_logic_file
1929    PROCEDURE copyto_register ( p_key IN VARCHAR2 ) IS
1930    BEGIN
1931 
1932       emit_regop_w ( register_index ( p_key ), 'copyto' );
1933 
1934    END copyto_register;
1935 ---------------------------------------------------------------------------------------
1936    -- Scope: compile_logic_file
1937    PROCEDURE aload_register ( p_key IN VARCHAR2 ) IS
1938    BEGIN
1939 
1940       IF ( NOT register_defined ( p_key )) THEN
1941 
1942         --#<should never happen>
1943         report_and_raise_sys_error(
1944             p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_UNDEFINED_REGISTER, 'KEY', p_key),
1945             p_run_id => x_run_id,
1946             p_model_id => p_component_id
1947         );
1948 
1949       END IF;
1950 
1951       emit_regop_w ( h_RegisterHash ( p_key ), 'aload' );
1952 
1953    END aload_register;
1954 ---------------------------------------------------------------------------------------
1955 ---------------------------------------------------------------------------------------
1956    -- Scope: compile_logic_file
1957    PROCEDURE create_array ( p_size IN PLS_INTEGER, p_type IN PLS_INTEGER ) IS
1958    BEGIN
1959 
1960       IF ( NOT cz_fce_compile_utils.assert_unsigned_byte ( p_type )) THEN
1961 
1962           report_and_raise_sys_error(
1963             p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_INCORRECT_IX, 'VALUE', TO_CHAR ( p_type )),
1964             p_run_id => x_run_id,
1965             p_model_id => p_component_id
1966         );
1967 
1968       END IF;
1969 
1970       push_integer_constant ( p_size );
1971       emit_code( h_inst ('newarray') || cz_fce_compile_utils.unsigned_byte ( p_type ));
1972 
1973    END create_array;
1974 ---------------------------------------------------------------------------------------
1975    -- Scope: compile_logic_file
1976    PROCEDURE populate_array_element ( p_index IN PLS_INTEGER ) IS
1977    BEGIN
1978 
1979       push_integer_constant ( p_index );
1980       emit_code( h_inst ('aastore'));
1981 
1982    END populate_array_element;
1983 ---------------------------------------------------------------------------------------
1984    -- Scope: compile_logic_file
1985    PROCEDURE populate_array ( p_size IN PLS_INTEGER ) IS
1986    BEGIN
1987 
1988       push_integer_constant ( p_size );
1989       emit_code( h_inst ('bulkaastore'));
1990 
1991    END populate_array;
1992 ---------------------------------------------------------------------------------------
1993    -- Scope: compile_logic_file
1994    PROCEDURE create_multi_array ( p_sizes IN type_integer_table, p_type IN PLS_INTEGER ) IS
1995 
1996       l_count   PLS_INTEGER;
1997 
1998    BEGIN
1999 
2000       IF ( NOT cz_fce_compile_utils.assert_unsigned_byte ( p_type )) THEN
2001 
2002           report_and_raise_sys_error(
2003             p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_INCORRECT_IX, 'VALUE', TO_CHAR ( p_type )),
2004             p_run_id => x_run_id,
2005             p_model_id => p_component_id
2006           );
2007 
2008       END IF;
2009 
2010       l_count := p_sizes.COUNT;
2011 
2012       IF ( NOT cz_fce_compile_utils.assert_unsigned_byte ( l_count )) THEN
2013 
2014           report_and_raise_sys_error(
2015             p_message => GET_NOT_TRANSLATED_TEXT(CZ_FCE_SE_EXCEED_INTTABLESIZE, 'VALUE', TO_CHAR ( l_count )),
2016             p_run_id => x_run_id,
2017             p_model_id => p_component_id
2018           );
2019 
2020       END IF;
2021 
2022       FOR i IN REVERSE 1..l_count LOOP
2023 
2024          push_integer_constant ( p_sizes ( i ));
2025 
2026       END LOOP;
2027 
2028       emit_code( h_inst ('multinewarray') || cz_fce_compile_utils.unsigned_byte ( l_count ) ||
2029                           cz_fce_compile_utils.unsigned_byte ( p_type ));
2030 
2031    END create_multi_array;
2032 ---------------------------------------------------------------------------------------
2033    -- Scope: compile_logic_file
2034    PROCEDURE emit_return IS
2035    BEGIN
2036 
2037       IF ( p_type = const_logicfile_def ) THEN
2038 
2039         emit_code ( h_inst ('areturn'));
2040 
2041       ELSE
2042 
2043         emit_code ( h_inst ('ret'));
2044 
2045       END IF;
2046    END emit_return;
2047 ---------------------------------------------------------------------------------------
2048 ------------------------------ HIGH LEVEL METHODS -------------------------------------
2049 ---------------------------------------------------------------------------------------
2050   PROCEDURE comment ( p_message IN VARCHAR2 ) IS
2051   BEGIN
2052 
2053     IF ( p_debug_mode = 1 ) THEN
2054 
2055       emit_comment ( p_message );
2056 
2057     END IF;
2058   END comment;
2059 ---------------------------------------------------------------------------------------
2060    --This procedure writes to the Constant Pool and pushed a variable name to the stack.
2061    --In the debug mode, the variable name is the structure node name.
2062    --In the regular mode, the variable name is the persistent id (as a string).
2063    -- Scope: compile_logic_file
2064 
2065    PROCEDURE push_variable_name ( p_index IN PLS_INTEGER ) IS
2066    BEGIN
2067 
2068       IF ( p_debug_mode = 1 ) THEN
2069 
2070         push_string_constant ( t_psn_name ( p_index ));
2071 
2072       ELSE
2073 
2074         push_string_constant( TO_CHAR ( t_psn_persistentnodeid ( p_index )));
2075 
2076       END IF;
2077    END push_variable_name;
2078 ---------------------------------------------------------------------------------------
2079    --This is the same procedure as above, but the input parameter is ps_node_id.
2080    -- Scope: compile_logic_file
2081 
2082    PROCEDURE push_variable_name ( p_id IN NUMBER ) IS
2083    BEGIN
2084 
2085       IF ( p_debug_mode = 1 ) THEN
2086 
2087         push_string_constant ( h_psnid_name ( TO_CHAR ( p_id )));
2088 
2089       ELSE
2090 
2091         push_string_constant( h_psnid_persistentnodeid ( TO_CHAR ( p_id )));
2092 
2093       END IF;
2094    END push_variable_name;
2095 ---------------------------------------------------------------------------------------
2096    --This procedure is used to store model defs in the local hash.
2097    --Note that model defs are hashed by persistent_node_id.
2098 
2099    --Here is why we need to hash by persistent_node_id, not ps_node_id. This procedure
2100    --will put a hash key on the stack and emit haload_0 instruction. The hash key will
2101    --be used to poke hash in order to get model def object. If there is no model def
2102    --for this key in the Interpreter's hash, the Interpreter must ask DIO for it.
2103    --DIO needs the referring node's persistent_node_id to be able to return model def.
2104    --So, to avoid conflicts, we need to always use persistent_node_id as the hash key.
2105 
2106    --However, because of using persistent_node_id, the model def hash (#0) can only be
2107    --used for 'local' model defs, or model defs, that are directly referenced from the
2108    --'local' model, not for remote models defs, retrieved with haload_2.
2109 
2110    -- Scope: compile_logic_file
2111 
2112    PROCEDURE hastore_def ( p_index IN PLS_INTEGER ) IS
2113    BEGIN
2114 
2115      hastore_object ( t_psn_persistentnodeid ( p_index ), 0);
2116 
2117    END hastore_def;
2118 ---------------------------------------------------------------------------------------
2119    --This procedure is used to load model defs from the local hash.
2120 
2121    --p_id - ps_node_id. Note that model defs are hashed by persistent_node_id.
2122    -- Scope: compile_logic_file
2123 
2124    PROCEDURE haload_def ( p_id IN NUMBER ) IS
2125    BEGIN
2126 
2127      haload_object ( h_psnid_persistentnodeid ( TO_CHAR ( p_id )), 0);
2128 
2129    END haload_def;
2130 ---------------------------------------------------------------------------------------
2131    --This procedure is used to retrieve model definitions, stored in a local variable.
2132    --Model definitions use ps_node_id as a hash key to allocate local variables.
2133 
2134    --Note that this procedure can be used as a universal access to 'local' model defs.
2135    --Even in port or constrain logic file, try to get model def from a local variable,
2136    --and if it is not there, get it from hash and store in a local variable.
2137 
2138    --Made a change to use this procedure for access to 'local' model defs.
2139    -- Scope: compile_logic_file
2140 
2141    PROCEDURE aload_model_def ( p_id IN NUMBER ) IS
2142 
2143      l_key  VARCHAR2(4000) := TO_CHAR ( p_id );
2144 
2145    BEGIN
2146 
2147       IF (NOT local_variable_defined ( l_key )) THEN
2148 
2149          --Model defs are always stored both in local variables and in hash. So, if it's
2150          --not in a local variable, meaning that the local variable has been overloaded,
2151          --we can get it from hash and re-store in a local variable.
2152 
2153          haload_def ( p_id );
2154          copyto_local_variable ( l_key );
2155 
2156       ELSE
2157 
2158          aload_local_variable ( l_key );
2159 
2160       END IF;
2161    END aload_model_def;
2162 ---------------------------------------------------------------------------------------
2163    --This procedure is used to store Solver variables in the local hash.
2164 
2165    --p_id - ps_node_id. Note that variable objects are hashed by ps_node_id.
2166    -- Scope: compile_logic_file
2167 
2168    PROCEDURE hastore_var ( p_index IN PLS_INTEGER ) IS
2169    BEGIN
2170 
2171        hastore_object ( t_psn_psnodeid ( p_index ), 1 );
2172 
2173    END hastore_var;
2174 ---------------------------------------------------------------------------------------
2175    PROCEDURE push_modeldef_name ( p_index IN PLS_INTEGER ) IS
2176 
2177      l_name   VARCHAR2(4000);
2178 
2179    BEGIN
2180 
2181       --Bug #6926688. For root models, we need to specify the repository model name
2182       --instead of ps_node name. We don't need to handle no_data_found here because
2183       --it will not get this far without the data.
2184 
2185       IF ( t_psn_parentid ( p_index ) IS NULL ) THEN
2186 
2187          SELECT name INTO l_name FROM cz_rp_entries
2188           WHERE deleted_flag = '0'
2189             AND object_type = 'PRJ'
2190             AND object_id = t_psn_psnodeid ( p_index );
2191 
2192          --Note that we always write name independently of debug mode.
2193 
2194          push_string_constant ( l_name );
2195          comment ( 'Create model: "' || l_name || '" (model_id = ' || t_psn_psnodeid ( p_index ) || ')');
2196 
2197       ELSE
2198 
2199          push_variable_name ( p_index );
2200 
2201       END IF;
2202    END push_modeldef_name;
2203 ---------------------------------------------------------------------------------------
2204    -- Scope: compile_logic_file
2205 
2206    PROCEDURE emit_model_def ( p_index IN PLS_INTEGER ) IS
2207 
2208      l_path       VARCHAR2(32000);
2209      l_id         NUMBER := t_psn_psnodeid ( p_index );
2210      l_parent_id  NUMBER;
2211 
2212    BEGIN
2213 
2214       push_modeldef_name ( p_index );
2215       emit_invokestatic ('Solver.createModelDef(String)');
2216 
2217       --If this is the root model, save the model def on stack to be returned at the
2218       --end.
2219 
2220       IF ( t_psn_parentid ( p_index ) IS NULL ) THEN emit_dup (); END IF;
2221 
2222       --Store in a hash and in a local variable.
2223 
2224       copyto_local_variable ( l_id );
2225       hastore_def ( p_index );
2226    END emit_model_def;
2227 ---------------------------------------------------------------------------------------
2228    PROCEDURE emit_effectivity ( p_classname   IN VARCHAR2
2229                               , p_eff_from    IN DATE
2230                               , p_eff_until   IN DATE
2231                               , p_eff_usages  IN VARCHAR2
2232                               ) IS
2233 
2234       l_eff_from     DATE := NVL ( p_eff_from, const_epoch_begin );
2235       l_eff_until    DATE := NVL ( p_eff_until, const_epoch_end );
2236       l_eff_usages   VARCHAR2(16) := LPAD ( p_eff_usages, 16, '0');
2237 
2238    BEGIN
2239 
2240         IF ( l_eff_from > const_epoch_begin ) THEN
2241 
2242             emit_dup ();
2243             push_date_constant ( l_eff_from );
2244 
2245             emit_invokevirtual ( p_classname || '.setEffectiveFrom(Date)');
2246             emit_pop ( 1 );
2247 
2248         END IF;
2249 
2250         IF ( l_eff_until < const_epoch_end ) THEN
2251 
2252             emit_dup ();
2253             push_date_constant ( l_eff_until );
2254 
2255             emit_invokevirtual ( p_classname || '.setEffectiveUntil(Date)');
2256             emit_pop ( 1 );
2257 
2258         END IF;
2259 
2260         IF ( l_eff_usages <> const_mask_all_usages ) THEN
2261 
2262             emit_dup ();
2263             push_mask_constant ( p_eff_usages );
2264 
2265             emit_invokevirtual ( p_classname || '.setEffectiveUsages(long)');
2266             emit_pop ( 1 );
2267 
2268         END IF;
2269    END emit_effectivity;
2270 ---------------------------------------------------------------------------------------
2271    -- Scope: compile_logic_file
2272    PROCEDURE emit_domainorder ( p_index IN PLS_INTEGER ) IS
2273    BEGIN
2274 
2275       --This handles NULL correctly: NULL <> 0 is false, nothing will be generated.
2276 
2277       IF ( t_psn_domainorder ( p_index ) <> 0) THEN
2278 
2279         --This method is called on a variable right after the variable is created, so the variable
2280         --is on the stack. Need to 'dup' because after calling this method the variable will again
2281         --be either haloaded or popped.
2282 
2283         emit_dup ();
2284 
2285         emit_invokevirtual (
2286              CASE t_psn_domainorder ( p_index )
2287                  WHEN const_domainorder_minfirst THEN 'IIntExprDef.setDomOrderMinFirst()'
2288                  WHEN const_domainorder_maxfirst THEN 'IIntExprDef.setDomOrderMaxFirst()'
2289                  WHEN const_domainorder_decmax THEN 'IIntExprDef.setDomOrderDecMax()'
2290                  WHEN const_domainorder_incmin THEN 'IIntExprDef.setDomOrderIncMin()'
2291                  WHEN const_domainorder_preffalse THEN 'IIntExprDef.setDomOrderMinFirst()'
2292                  WHEN const_domainorder_preftrue THEN 'IIntExprDef.setDomOrderMaxFirst()'
2293              END);
2294 
2295         --Void methods push null, need to pop it from the stack.
2296 
2297         emit_pop ( 1 );
2298       END IF;
2299    END emit_domainorder;
2300 ---------------------------------------------------------------------------------------
2301    PROCEDURE emit_setid ( p_index IN PLS_INTEGER ) IS
2302    BEGIN
2303 
2304       emit_dup ();
2305       push_long_constant ( t_psn_persistentnodeid ( p_index ));
2306       emit_invokevirtual ('IExprDef.setId(long)');
2307 
2308       --Remove the null object from stack after a void method.
2309 
2310       emit_pop ( 1 );
2311 
2312    END emit_setid;
2313 ---------------------------------------------------------------------------------------
2314    -- Scope: compile_logic_file
2315    PROCEDURE emit_logicvar ( p_index IN PLS_INTEGER ) IS
2316    BEGIN
2317 
2318       aload_model_def ( t_psn_parentid (p_index));
2319       push_variable_name ( p_index );
2320 
2321       emit_invokevirtual ('IModelDef.logicVar(String)');
2322       emit_domainorder ( p_index );
2323 
2324       emit_effectivity ( 'ILogicExprDef', t_psn_effectivefrom ( p_index ), t_psn_effectiveuntil ( p_index ), t_psn_effectiveusagemask ( p_index ));
2325 
2326       emit_setid ( p_index );
2327       hastore_var ( p_index );
2328    END emit_logicvar;
2329 ---------------------------------------------------------------------------------------
2330    -- Scope: compile_logic_file
2331    PROCEDURE emit_intvar ( p_index IN PLS_INTEGER
2332                          , p_min   IN NUMBER
2333                          , p_max   IN NUMBER
2334                          ) IS
2335 
2336      l_ptr  PLS_INTEGER;
2337 
2338    BEGIN
2339 
2340       aload_model_def ( t_psn_parentid (p_index));
2341       push_variable_name ( p_index );
2342 
2343       push_integer_constant ( p_min );
2344       push_integer_constant ( p_max );
2345 
2346       emit_invokevirtual ('IModelDef.intVar(String, int, int)');
2347       emit_domainorder ( p_index );
2348 
2349       emit_setid ( p_index );
2350       hastore_var ( p_index );
2351    END emit_intvar;
2352 ---------------------------------------------------------------------------------------
2353    -- Scope: compile_logic_file
2354    PROCEDURE emit_floatvar ( p_index IN PLS_INTEGER
2355                            , p_min   IN NUMBER
2356                            , p_max   IN NUMBER
2357                            ) IS
2358    BEGIN
2359 
2360       aload_model_def ( t_psn_parentid (p_index));
2361       push_variable_name ( p_index );
2362 
2363       --Null values should not be allowed.
2364 
2365       push_double_constant ( p_min );
2366       push_double_constant ( p_max );
2367 
2368       emit_invokevirtual ('IModelDef.floatVar(String, double, double)');
2369       emit_domainorder ( p_index );
2370 
2371       emit_setid ( p_index );
2372       hastore_var ( p_index );
2373    END emit_floatvar;
2374 ---------------------------------------------------------------------------------------
2375    -- Scope: compile_logic_file
2376    --This procedure pushes on the stack the parent's object and the current variable
2377    --name. It is called for a feature to put the first two parameters of the feature
2378    --method on the stack before the options array.
2379    -- Scope: compile_logic_file
2380    PROCEDURE prepare_feature ( p_index IN PLS_INTEGER) IS
2381    BEGIN
2382 
2383       aload_model_def ( t_psn_parentid (p_index));
2384       push_variable_name ( p_index );
2385 
2386    END prepare_feature;
2387 ---------------------------------------------------------------------------------------
2388    -- Scope: compile_logic_file
2389    PROCEDURE emit_bagvar( p_index          IN PLS_INTEGER
2390                         , p_option_count   IN PLS_INTEGER
2391                         , p_cardmin        IN NUMBER
2392                         , p_cardmax        IN NUMBER
2393                         , p_countmin       IN NUMBER
2394                         , p_countmax       IN NUMBER
2395                         , p_max_option_qty IN NUMBER
2396                         ) IS
2397    BEGIN
2398 
2399       create_array ( p_option_count, h_javatypes('Object'));
2400       populate_array ( p_option_count );
2401       push_integer_constant ( p_cardmin );
2402       push_integer_constant ( p_cardmax );
2403       push_integer_constant ( p_countmin );
2404       push_integer_constant ( p_countmax );
2405       push_integer_constant ( p_max_option_qty );
2406 
2407       emit_invokevirtual ('IModelDef.bagVar(String, Object[], int, int, int, int, int)');
2408       emit_effectivity ( 'ISetExprDef', t_psn_effectivefrom ( p_index ), t_psn_effectiveuntil ( p_index ), t_psn_effectiveusagemask ( p_index ));
2409 
2410       emit_setid ( p_index );
2411       hastore_var ( p_index );
2412    END emit_bagvar;
2413 ---------------------------------------------------------------------------------------
2414    -- Scope: compile_logic_file
2415    PROCEDURE emit_setvar( p_index        IN PLS_INTEGER
2416                         , p_option_count IN PLS_INTEGER
2417                         , p_cardmin      IN NUMBER
2418                         , p_cardmax      IN NUMBER
2419                         ) IS
2420    BEGIN
2421 
2422       create_array ( p_option_count, h_javatypes('Object'));
2423       populate_array ( p_option_count );
2424       push_integer_constant ( p_cardmin );
2425       push_integer_constant ( p_cardmax );
2426 
2427       emit_invokevirtual ('IModelDef.setVar(String, Object[], int, int)');
2428       emit_effectivity ( 'ISetExprDef', t_psn_effectivefrom ( p_index ), t_psn_effectiveuntil ( p_index ), t_psn_effectiveusagemask ( p_index ));
2429 
2430       emit_setid ( p_index );
2431       hastore_var ( p_index );
2432    END emit_setvar;
2433 ---------------------------------------------------------------------------------------
2434    -- Scope: compile_logic_file
2435    PROCEDURE emit_singletonvar( p_index IN PLS_INTEGER ) IS
2436 
2437      l_id  NUMBER := t_psn_psnodeid ( p_index );
2438 
2439    BEGIN
2440 
2441       aload_model_def ( t_psn_parentid (p_index));
2442       push_variable_name ( p_index );
2443       aload_model_def ( l_id );
2444       emit_invokevirtual ('IModelDef.singletonVar(String, IModelDef)');
2445 
2446       emit_setid ( p_index );
2447       hastore_var ( p_index );
2448    END emit_singletonvar;
2449 ---------------------------------------------------------------------------------------
2450    -- Scope: compile_logic_file
2451    PROCEDURE emit_instancesetvar( p_index    IN PLS_INTEGER
2452                                 , p_cardmin  IN NUMBER
2453                                 , p_cardmax  IN NUMBER
2454                                 ) IS
2455    BEGIN
2456 
2457       aload_model_def ( t_psn_parentid (p_index));
2458       push_variable_name ( p_index );
2459 
2460       --#<dio integration>
2461       --A call to DIO will be made to retrieve the model def of the referenced model. The
2462       --referenced model is uniquely identified by the reference's persistent_node_id
2463       --within the context of the referencing model.
2464 
2465       aload_model_def ( t_psn_psnodeid (p_index));
2466       push_integer_constant ( p_cardmin );
2467       push_integer_constant ( p_cardmax );
2468 
2469       emit_invokevirtual ('IModelDef.instanceSetVar(String, IModelDef, int, int)');
2470       emit_effectivity ( 'IPortExprDef', t_psn_effectivefrom ( p_index ), t_psn_effectiveuntil ( p_index ), t_psn_effectiveusagemask ( p_index ));
2471 
2472       emit_setid ( p_index );
2473 
2474       --Variables can be only referenced in rule or port logic files, so there is
2475       --no need to store them in a local variable.
2476 
2477       hastore_var ( p_index );
2478    END emit_instancesetvar;
2479 ---------------------------------------------------------------------------------------
2480    -- Scope: compile_logic_file
2481    PROCEDURE emit_connectorsetvar( p_index    IN PLS_INTEGER
2482                                  , p_cardmin  IN NUMBER
2483                                  , p_cardmax  IN NUMBER
2484                                  ) IS
2485    BEGIN
2486 
2487       aload_model_def ( t_psn_parentid (p_index));
2488       push_variable_name ( p_index );
2489 
2490       --#<dio integration>
2491       --A call to DIO will be made to retrieve the model def of the referenced model. The
2492       --referenced model is uniquely identified by the reference's persistent_node_id
2493       --within the context of the referencing model.
2494 
2495       aload_model_def ( t_psn_psnodeid (p_index));
2496       push_integer_constant ( p_cardmin );
2497       push_integer_constant ( p_cardmax );
2498 
2499       emit_invokevirtual ('IModelDef.connectorSetVar(String, IModelDef, int, int)');
2500       emit_effectivity ( 'IPortExprDef', t_psn_effectivefrom ( p_index ), t_psn_effectiveuntil ( p_index ), t_psn_effectiveusagemask ( p_index ));
2501 
2502       emit_setid ( p_index );
2503       hastore_var ( p_index );
2504    END emit_connectorsetvar;
2505 ---------------------------------------------------------------------------------------
2506    -- Scope: compile_logic_file
2507    PROCEDURE emit_bommodel_def ( p_index        IN PLS_INTEGER
2508                                , p_decimal_flag IN VARCHAR2
2509                                ) IS
2510 
2511      l_id   NUMBER := t_psn_psnodeid ( p_index );
2512 
2513    BEGIN
2514 
2515       push_modeldef_name ( p_index );
2516       emit_boolean ( p_decimal_flag );
2517       emit_invokestatic ('Solver.createBomModelDef(String, boolean)');
2518 
2519       --If this is the root model, save the model def on stack to be returned at the end.
2520 
2521       IF ( t_psn_parentid ( p_index ) IS NULL) THEN emit_dup (); END IF;
2522 
2523       --Store in a hash and in a local variable.
2524 
2525       copyto_local_variable ( l_id );
2526       hastore_def ( p_index );
2527    END emit_bommodel_def;
2528 ---------------------------------------------------------------------------------------
2529    -- Scope: compile_logic_file
2530    PROCEDURE emit_bomoptionclass_def ( p_index        IN PLS_INTEGER
2531                                      , p_decimal_flag IN VARCHAR2
2532                                      ) IS
2533 
2534      l_id   NUMBER := t_psn_psnodeid ( p_index );
2535 
2536    BEGIN
2537 
2538       push_variable_name ( p_index );
2539       emit_boolean ( p_decimal_flag );
2540       emit_invokestatic ('Solver.createBomOCDef(String, boolean)');
2541 
2542       --Option class definition is used to create the child standard items, and also the
2543       --option class variable. Those will be always in the same file, and access the def
2544       --via a local variable.
2545 
2546       --Also need to hastore, because if there is a reference to another bom model under
2547       --this option class, the bomModelVar will be called on this object in a different
2548       --logic file.
2549 
2550       copyto_local_variable ( l_id );
2551       hastore_def ( p_index );
2552    END emit_bomoptionclass_def;
2553 ---------------------------------------------------------------------------------------
2554    -- Scope: compile_logic_file
2555    PROCEDURE emit_bommodelvar ( p_index         IN PLS_INTEGER
2556                               , p_decimal_flag  IN VARCHAR2
2557                               , p_required_flag IN VARCHAR2
2558                               , p_min_qty       IN NUMBER
2559                               , p_max_qty       IN NUMBER
2560                               , p_def_qty       IN NUMBER
2561                               , p_cardmin       IN NUMBER
2562                               , p_cardmax       IN NUMBER
2563                               , p_eff_from      IN DATE
2564                               , p_eff_until     IN DATE
2565                               , p_eff_mask      IN VARCHAR2
2566                               ) IS
2567    BEGIN
2568 
2569       aload_model_def ( t_psn_parentid ( p_index ));
2570       push_variable_name ( p_index );
2571 
2572       --#<dio integration>
2573       --A call to DIO will be made to retrieve the model def of the referenced model. The
2574       --referenced model is uniquely identified by the reference's persistent_node_id
2575       --within the context of the referencing model.
2576 
2577       aload_model_def ( t_psn_psnodeid ( p_index ));
2578       emit_boolean ( p_required_flag );
2579 
2580       IF ( p_decimal_flag = '0') THEN
2581 
2582          push_integer_constant ( p_min_qty );
2583          push_integer_constant ( p_max_qty );
2584          push_integer_constant ( p_def_qty );
2585          push_integer_constant ( p_cardmin );
2586          push_integer_constant ( p_cardmax );
2587 
2588       ELSE
2589 
2590          push_double_constant ( p_min_qty );
2591          push_double_constant ( p_max_qty );
2592          push_double_constant ( p_def_qty );
2593          push_double_constant ( p_cardmin );
2594          push_double_constant ( p_cardmax );
2595 
2596       END IF;
2597 
2598       push_date_constant ( p_eff_from );
2599       push_date_constant ( p_eff_until );
2600       push_mask_constant ( p_eff_mask );
2601 
2602       IF ( p_decimal_flag = '0' ) THEN
2603 
2604          emit_invokevirtual ('IModelDef.bomModelVar(String, IBomModelDef, boolean, int, int, int, int, int, Date, Date, long)');
2605 
2606       ELSE
2607 
2608          emit_invokevirtual ('IModelDef.bomModelVar(String, IBomModelDef, boolean, double, double, double, int, int, Date, Date, long)');
2609 
2610       END IF;
2611 
2612       emit_setid ( p_index );
2613       hastore_var ( p_index );
2614    END emit_bommodelvar;
2615 ---------------------------------------------------------------------------------------
2616    -- Scope: compile_logic_file
2617    PROCEDURE emit_bomoptionclassvar ( p_index         IN PLS_INTEGER
2618                                     , p_decimal_flag  IN VARCHAR2
2619                                     , p_required_flag IN VARCHAR2
2620                                     , p_min_qty       IN NUMBER
2621                                     , p_max_qty       IN NUMBER
2622                                     , p_def_qty       IN NUMBER
2623                                     , p_minselected   IN NUMBER
2624                                     , p_maxselected   IN NUMBER
2625                                     , p_eff_from      IN DATE
2626                                     , p_eff_until     IN DATE
2627                                     , p_eff_mask      IN VARCHAR2
2628                                     ) IS
2629 
2630      l_id   NUMBER := t_psn_psnodeid ( p_index );
2631 
2632    BEGIN
2633 
2634       --Is there a reason not to use local variable here?
2635 
2636       aload_model_def ( t_psn_parentid (p_index));
2637       push_variable_name ( p_index );
2638       aload_model_def ( l_id );
2639       emit_boolean ( p_required_flag );
2640 
2641       IF ( p_decimal_flag = '0' ) THEN
2642 
2643          push_integer_constant ( p_min_qty );
2644          push_integer_constant ( p_max_qty );
2645          push_integer_constant ( p_def_qty );
2646          push_integer_constant ( p_minselected );
2647          push_integer_constant ( p_maxselected );
2648 
2649       ELSE
2650 
2651          push_double_constant ( p_min_qty );
2652          push_double_constant ( p_max_qty );
2653          push_double_constant ( p_def_qty );
2654          push_double_constant ( p_minselected );
2655          push_double_constant ( p_maxselected );
2656 
2657       END IF;
2658 
2659       push_date_constant ( p_eff_from );
2660       push_date_constant ( p_eff_until );
2661       push_mask_constant ( p_eff_mask );
2662 
2663       IF ( p_decimal_flag = '0') THEN
2664 
2665          emit_invokevirtual ('IBomDef.bomOptionClassVar(String, IBomOCDef, boolean, int, int, int, int, int, Date, Date, long)');
2666 
2667       ELSE
2668 
2669          emit_invokevirtual ('IBomDef.bomOptionClassVar(String, IBomOCDef, boolean, double, double, double, int, int, Date, Date, long)');
2670 
2671       END IF;
2672 
2673       emit_setid ( p_index );
2674       hastore_var ( p_index );
2675    END emit_bomoptionclassvar;
2676 ---------------------------------------------------------------------------------------
2677    -- Scope: compile_logic_file
2678    PROCEDURE emit_bomstandarditemvar ( p_index         IN PLS_INTEGER
2679                                      , p_decimal_flag  IN VARCHAR2
2680                                      , p_required_flag IN VARCHAR2
2681                                      , p_min_qty       IN NUMBER
2682                                      , p_max_qty       IN NUMBER
2683                                      , p_def_qty       IN NUMBER
2684                                      , p_eff_from      IN DATE
2685                                      , p_eff_until     IN DATE
2686                                      , p_eff_mask      IN VARCHAR2
2687                                      ) IS
2688    BEGIN
2689 
2690       --Is there a reason not to use local variable here?
2691 
2692       aload_model_def ( t_psn_parentid (p_index));
2693       push_variable_name ( p_index );
2694       emit_boolean ( p_required_flag );
2695 
2696       IF ( p_decimal_flag = '0' ) THEN
2697 
2698          push_integer_constant ( p_min_qty );
2699          push_integer_constant ( p_max_qty );
2700          push_integer_constant ( p_def_qty );
2701 
2702       ELSE
2703 
2704          push_double_constant ( p_min_qty );
2705          push_double_constant ( p_max_qty );
2706          push_double_constant ( p_def_qty );
2707 
2708       END IF;
2709 
2710       push_date_constant ( p_eff_from );
2711       push_date_constant ( p_eff_until );
2712       push_mask_constant ( p_eff_mask );
2713 
2714       IF ( p_decimal_flag = '0' ) THEN
2715 
2716          emit_invokevirtual ('IBomDef.bomStandardItemVar(String, boolean, int, int, int, Date, Date, long)');
2717 
2718       ELSE
2719 
2720          emit_invokevirtual ('IBomDef.bomStandardItemVar(String, boolean, double, double, double, Date, Date, long)');
2721 
2722       END IF;
2723 
2724       emit_setid ( p_index );
2725       hastore_var ( p_index );
2726    END emit_bomstandarditemvar;
2727 ---------------------------------------------------------------------------------------
2728    -- Scope: compile_logic_file
2729    PROCEDURE emit_reverseport ( p_index IN PLS_INTEGER) IS
2730    BEGIN
2731 
2732       --This is a local variable. This only works if this port is a direct child of its own root.
2733 
2734       haload_object ( t_psn_psnodeid (p_index), 1 );
2735 
2736       --This is a remote variable in a direct child model. This only works if this port is
2737       --a direct child of its own root.
2738 
2739       push_variable_name ( t_psn_reverseportid (p_index));
2740       haload2_object ( t_psn_persistentnodeid (p_index));
2741 
2742       emit_invokevirtual ('IPortExprDef.setReversePort(IPortExprDef)');
2743 
2744       --#<optimization-reverseport>:Void methods push null, need to pop it from the stack.
2745       --We do not pop it here in order to implement optimization.
2746    END emit_reverseport;
2747 ---------------------------------------------------------------------------------------
2748    -- Scope: compile_logic_file
2749    PROCEDURE create_feature ( p_index         IN PLS_INTEGER
2750                             , p_option_count  IN PLS_INTEGER
2751                             , p_var_min       IN NUMBER
2752                             , p_var_max       IN NUMBER
2753                             , p_var_count     IN NUMBER
2754                             ) IS
2755    BEGIN
2756 
2757       CASE t_psn_countedoptionsflag ( p_index )
2758 
2759          WHEN '1' THEN
2760 
2761             IF ( p_var_count = 0 ) THEN
2762 
2763                report_and_raise_sys_error(
2764                 p_message => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SE_OPTION_MAXQ_NOT_ZERO,
2765                     'NODE_NAME', CZ_FCE_COMPILE_UTILS.GET_NODE_PATH (
2766                       t_psn_psnodeid ( p_index ),
2767                       ps_node_id_table_to_string(
2768                                 build_model_path(t_psn_psnodeid ( p_index )) ) ) ),
2769                 p_run_id => x_run_id,
2770                 p_model_id => p_component_id
2771               );
2772 
2773             END IF;
2774 
2775             emit_bagvar( p_index
2776                        , p_option_count
2777                        , p_var_min
2778                        , p_var_max * p_var_count
2779                        , p_var_min
2780                        , p_var_max
2781                        , p_var_count
2782                        );
2783 
2784          ELSE
2785 
2786             emit_setvar( p_index
2787                        , p_option_count
2788                        , p_var_min
2789                        , p_var_max
2790                        );
2791 
2792       END CASE;
2793    END create_feature;
2794 ---------------------------------------------------------------------------------------
2795 ---------------------------------------------------------------------------------------
2796 ---------------------------------------------------------------------------------------
2797    -- Scope: compile_logic_file
2798    FUNCTION is_bom_port ( p_index IN PLS_INTEGER ) RETURN BOOLEAN IS
2799    BEGIN
2800 
2801       RETURN t_psn_psnodetype ( p_index ) IN ( h_psntypes ('reference'), h_psntypes ('connector')) AND
2802                  h_psnid_psnodetype ( TO_CHAR ( t_psn_referenceid ( p_index ))) =
2803                      h_psntypes ('bommodel');
2804 
2805    END is_bom_port;
2806 ---------------------------------------------------------------------------------------
2807    -- Scope: compile_logic_file
2808    FUNCTION is_bom_node ( p_index IN PLS_INTEGER ) RETURN BOOLEAN IS
2809    BEGIN
2810 
2811       RETURN t_psn_psnodetype ( p_index ) IN ( h_psntypes ('bomoptionclass'), h_psntypes ('bommodel'), h_psntypes ('bomstandard'));
2812 
2813    END is_bom_node;
2814 ---------------------------------------------------------------------------------------
2815    -- Scope: compile_logic_file
2816    FUNCTION is_bom ( p_index IN PLS_INTEGER ) RETURN BOOLEAN IS
2817    BEGIN
2818 
2819       RETURN is_bom_node ( p_index ) OR is_bom_port ( p_index );
2820 
2821    END is_bom;
2822 ---------------------------------------------------------------------------------------
2823 ---------------------------------------------------------------------------------------
2824 ---------------------------------------------------------------------------------------
2825    -- Scope: compile_logic_file
2826    PROCEDURE compile_constraints IS
2827 
2828      t_expl_modelrefexplid        type_number_table;
2829      t_expl_parentexplnodeid      type_number_table;
2830      t_expl_componentid           type_number_table;
2831      t_expl_referringnodeid       type_number_table;
2832      t_expl_explnodetype          type_number_table;
2833 
2834      h_explid_backindex           type_data_hashtable;
2835      h_parentid_referring_explid  type_nodehashtable_hashtable;
2836 
2837      t_exp_modelrefexplid         type_number_table;
2838      t_exp_exprtype               type_number_table;
2839      t_exp_exprnodeid             type_number_table;
2840      t_exp_exprparentid           type_number_table;
2841      t_exp_templateid             type_number_table;
2842      t_exp_psnodeid               type_number_table;
2843      t_exp_datavalue              type_varchar4000_table;
2844      t_exp_propertyid             type_number_table;
2845      t_exp_paramindex             type_number_table;
2846      t_exp_argumentindex          type_number_table;
2847      t_exp_argumentname           type_varchar4000_table;
2848      t_exp_datatype               type_number_table;
2849      t_exp_datanumvalue           type_number_table;
2850      t_exp_paramsignatureid       type_number_table;
2851      t_exp_relativenodepath       type_varchar4000_table;
2852      t_exp_seqnbr                 type_number_table;
2853 
2854      h_exprid_childrenindex       type_data_hashtable;
2855      h_exprid_backindex           type_data_hashtable;
2856      h_exprid_numberofchildren    type_data_hashtable;
2857      t_instancequantifiers        type_varchar4000_table;
2858      h_instancequantifiers        type_data_hashtable;
2859 
2860      h_propertyid_datatype        type_node_hashtable;
2861      h_propertyid_type            type_node_hashtable;
2862      h_propertyid_defvalue        type_name_hashtable;
2863      h_psnid_propertyid_value     type_name_hashtable;
2864 
2865      t_acc_complete_path          type_numbertable_table;
2866      t_acc_targets                type_varchar4000_table;
2867      t_acc_target_sequence        type_integer_table;
2868      t_acc_local_quantifiers      type_varchar4000_table;
2869      t_acc_contributors           type_contributortable_table;
2870      t_acc_quantifiers            type_varchar4000table_table;
2871      h_acc_targets                type_data_hashtable;
2872      h_acc_quantifiers            type_datahashtable_table;
2873      t_target_quantifiers         type_varchar4000table_table;
2874      h_target_quantifiers         type_datahashtable_table;
2875 
2876      h_parameter_stack            type_iteratorhashtable_table;
2877      t_argument_table             type_integertable_table;
2878 
2879      l_rule_expr_lastindex        PLS_INTEGER;
2880      l_input_context              expression_context;
2881      l_output_context             expression_context;
2882 
2883      this_rule_id                 NUMBER;
2884      this_reason_id               NUMBER;
2885      this_rule_class              NUMBER;
2886      this_rule_name               VARCHAR2(255);
2887      this_effective_from          DATE;
2888      this_effective_until         DATE;
2889      this_effective_usages        VARCHAR2(16);
2890 
2891      l_key                        VARCHAR2(4000);
2892      l_count                      PLS_INTEGER;
2893      l_run_id                     NUMBER;
2894 
2895      assistant_var_id             PLS_INTEGER := 0;
2896      target_count_svp             PLS_INTEGER;
2897 
2898      contributor_validation       PLS_INTEGER;
2899 
2900      ----------------------------------------------------------------------------------
2901      -- This procedure reports user rule warning and by default raises
2902      -- CZ_LOGICGEN_WARNING exception. Optional p_warning_location can be
2903      -- specified to record the code location of the warning (like method where
2904      -- the warning occurred). Warning location is stored in the error_stack column
2905      -- of the cz_db_logs table.
2906      -- Scope: compile_constraints
2907      PROCEDURE report_and_raise_rule_warning (
2908         p_text IN VARCHAR2,
2909         p_warning_location IN VARCHAR2 DEFAULT NULL ) IS
2910 
2911      BEGIN
2912        report_and_raise_warning(
2913                 p_message => p_text,
2914                 p_run_id => x_run_id,
2915                 p_model_id => p_component_id,
2916                 p_ps_node_id => NULL,
2917                 p_rule_id => this_rule_id,
2918                 p_error_stack => p_warning_location
2919               );
2920      END report_and_raise_rule_warning;
2921 
2922      -- This procedure reports user rule warning and by default raises
2923      -- CZ_LOGICGEN_WARNING exception. This procedure substitutes the rule_name
2924      -- and model_name parameters in the given message. Optional p_warning_location can be
2925      -- specified to record the code location of the warning (like method where
2926      -- the warning occurred). Warning location is stored in the error_stack column
2927      -- of the cz_db_logs table.
2928      -- Scope: compile_constraints
2929      PROCEDURE report_and_raise_rule_sys_warn (
2930         p_text IN VARCHAR2,
2931         p_warning_location IN VARCHAR2 DEFAULT NULL ) IS
2932 
2933      BEGIN
2934 
2935        report_and_raise_sys_warning(
2936                 p_message => GET_NOT_TRANSLATED_TEXT(
2937                                 p_text,
2938                                 'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
2939                                 'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
2940                 p_run_id => x_run_id,
2941                 p_model_id => p_component_id,
2942                 p_ps_node_id => NULL,
2943                 p_rule_id => this_rule_id,
2944                 p_error_stack => p_warning_location
2945               );
2946      END report_and_raise_rule_sys_warn;
2947 
2948      ----------------------------------------------------------------------------------
2949      -- Scope: compile_constraints
2950      FUNCTION build_reference_path ( p_expl_id IN NUMBER ) RETURN type_number_table IS
2951 
2952        l_expl_id     VARCHAR2(4000) := TO_CHAR ( p_expl_id );
2953        l_key         VARCHAR2(4000);
2954        l_index       PLS_INTEGER;
2955        tl_id_path    type_number_table;
2956 
2957      BEGIN
2958 
2959        IF ( h_explid_referencepath.EXISTS ( l_expl_id )) THEN RETURN h_explid_referencepath ( l_expl_id ); END IF;
2960 
2961        l_key := l_expl_id;
2962 
2963        BEGIN
2964 
2965           WHILE ( l_expl_id IS NOT NULL ) LOOP
2966 
2967              l_index := h_explid_backindex ( l_expl_id );
2968 
2969              IF ( t_expl_referringnodeid ( l_index ) IS NOT NULL ) THEN
2970 
2971                 --This is a reference or connector.
2972 
2973                 tl_id_path ( tl_id_path.COUNT + 1 ) := t_expl_referringnodeid ( l_index );
2974 
2975              END IF;
2976 
2977              l_expl_id := TO_CHAR ( t_expl_parentexplnodeid ( l_index ));
2978           END LOOP;
2979 
2980        EXCEPTION
2981           WHEN OTHERS THEN
2982 
2983               --#<should never happen>
2984               report_and_raise_rule_sys_warn(
2985                 GET_NOT_TRANSLATED_TEXT(
2986                     CZ_FCE_SW_INCORRECT_EXPL_ID,
2987                     'EXPLOSION_ID', l_expl_id),
2988                 p_warning_location => 'build_reference_path');
2989        END;
2990 
2991        h_explid_referencepath ( l_key ) := tl_id_path;
2992 
2993        RETURN tl_id_path;
2994      END build_reference_path;
2995      ----------------------------------------------------------------------------------
2996      -- Scope: compile_constraints
2997      FUNCTION build_complete_path ( p_node_id IN NUMBER, p_expl_id IN NUMBER ) RETURN type_number_table IS
2998 
2999        tl_complete_path   type_number_table;
3000        tl_reference_path  type_number_table;
3001        tl_model_path      type_number_table;
3002 
3003        l_key              VARCHAR2(4000);
3004        l_start            PLS_INTEGER := 1;
3005 
3006      BEGIN
3007 
3008        l_key := TO_CHAR ( p_node_id ) || '_' || TO_CHAR ( p_expl_id );
3009        IF ( h_psnid_explid_completepath.EXISTS ( l_key )) THEN RETURN h_psnid_explid_completepath ( l_key ); END IF;
3010 
3011        tl_complete_path := build_model_path ( p_node_id );
3012        tl_reference_path :=  build_reference_path ( p_expl_id );
3013 
3014        IF ( tl_reference_path.COUNT = 0 ) THEN
3015 
3016           h_psnid_explid_completepath ( l_key ) := tl_complete_path;
3017           RETURN tl_complete_path;
3018 
3019        END IF;
3020 
3021        IF ( h_psnid_psnodetype ( TO_CHAR ( p_node_id )) IN ( h_psntypes ('reference'), h_psntypes ('connector'))) THEN
3022 
3023           --If the node is a reference or connector itself, we need to cut off its own explosion,
3024           --which is the first element because the array is populated bottom up.
3025 
3026           l_start := 2;
3027 
3028        END IF;
3029 
3030        FOR i IN l_start..tl_reference_path.COUNT LOOP
3031 
3032           tl_model_path := build_model_path ( tl_reference_path ( i ));
3033 
3034           FOR ii IN 1..tl_model_path.COUNT LOOP
3035 
3036              tl_complete_path ( tl_complete_path.COUNT + 1 ) := tl_model_path ( ii );
3037 
3038           END LOOP;
3039        END LOOP;
3040 
3041        h_psnid_explid_completepath ( l_key ) := tl_complete_path;
3042 
3043        RETURN tl_complete_path;
3044      END build_complete_path;
3045      ----------------------------------------------------------------------------------
3046     -- Scope: compile_constraints
3047      PROCEDURE generate_expression ( j IN PLS_INTEGER
3048                                    , p_input_context IN expression_context
3049                                    , x_output_context IN OUT NOCOPY expression_context );
3050      ----------------------------------------------------------------------------------
3051      -- Scope: compile_constraints
3052      PROCEDURE set_rule_savepoint IS
3053      BEGIN
3054 
3055         set_savepoint ();
3056         target_count_svp := t_acc_targets.COUNT;
3057 
3058      END set_rule_savepoint;
3059      ----------------------------------------------------------------------------------
3060      -- Scope: compile_constraints
3061      PROCEDURE restore_rule_savepoint IS
3062      BEGIN
3063 
3064         restore_savepoint ();
3065         t_acc_targets.DELETE ( target_count_svp + 1, t_acc_targets.COUNT );
3066 
3067      END restore_rule_savepoint;
3068      ----------------------------------------------------------------------------------
3069    -- Scope: compile_logic_file
3070      PROCEDURE sum_numeric ( p_count IN PLS_INTEGER ) IS
3071      BEGIN
3072 
3073         IF ( p_count = 2 ) THEN
3074 
3075            --There are two distinct values, use addition instead of sum.
3076 
3077            emit_invokevirtual ('INumExprDef.sum(INumExprDef)');
3078 
3079         ELSIF ( p_count > 2 ) THEN
3080 
3081            --In general case create an array of parameters and call IModelDef.sum. The model def
3082            --for that should already be on stack.
3083 
3084            create_array ( p_count, h_javatypes ('INumExprDef'));
3085            populate_array ( p_count );
3086            emit_invokevirtual ('IModelDef.sum(INumExprDef[])');
3087 
3088         END IF;
3089      END sum_numeric;
3090      ----------------------------------------------------------------------------------
3091      -- Scope: compile_constraints
3092      PROCEDURE clear_argument_table IS
3093      BEGIN
3094 
3095         IF ( t_argument_table.EXISTS ( h_parameter_stack.COUNT )) THEN
3096 
3097            t_argument_table ( h_parameter_stack.COUNT ).DELETE;
3098 
3099         END IF;
3100      END clear_argument_table;
3101      ----------------------------------------------------------------------------------
3102      -- Scope: compile_constraints
3103      PROCEDURE add_argument ( j IN PLS_INTEGER ) IS
3104 
3105         l_count  PLS_INTEGER := 1;
3106 
3107      BEGIN
3108 
3109         IF ( t_argument_table.EXISTS ( h_parameter_stack.COUNT )) THEN
3110 
3111            l_count := t_argument_table ( h_parameter_stack.COUNT ).COUNT + 1;
3112 
3113         END IF;
3114 
3115         t_argument_table ( h_parameter_stack.COUNT )( l_count ) := j;
3116 
3117      END add_argument;
3118      ----------------------------------------------------------------------------------
3119      -- Scope: compile_constraints
3120      PROCEDURE restore_arguments IS
3121      BEGIN
3122 
3123         IF ( t_argument_table.EXISTS ( h_parameter_stack.COUNT )) THEN
3124 
3125            FOR i IN 1..t_argument_table ( h_parameter_stack.COUNT ).COUNT LOOP
3126 
3127               t_exp_exprtype ( t_argument_table ( h_parameter_stack.COUNT )( i )) := h_exprtypes ('argument');
3128 
3129            END LOOP;
3130         END IF;
3131      END restore_arguments;
3132      ----------------------------------------------------------------------------------
3133      -- Scope: compile_constraints
3134      FUNCTION retrieve_parameter ( p_name IN VARCHAR2 ) RETURN type_iterator_value IS
3135 
3136         l_count   PLS_INTEGER;
3137 
3138      BEGIN
3139 
3140         --When generating or looking up a parameter, it is always enough to look up only
3141         --on top of the stack. We only look up parameters during parsing of where clause
3142         --which happens before the forall, currently being generated, puts parameters on
3143         --the stack, so at this moment the parameter from the outer forall, which we are
3144         --looking up, should be on top of the stack.
3145 
3146         l_count := h_parameter_stack.COUNT;
3147 
3148         IF ( NOT h_parameter_stack ( l_count ).EXISTS ( p_name )) THEN
3149 
3150            --#<should never happen>
3151            report_and_raise_rule_sys_warn (
3152                 p_text => GET_NOT_TRANSLATED_TEXT (
3153                         CZ_FCE_SW_NO_VALUE_PARAMSTK,
3154                         'PARAM', p_name ),
3155                 p_warning_location => 'retrieve_parameter' );
3156 
3157         END IF;
3158 
3159         RETURN h_parameter_stack ( l_count )( p_name );
3160 
3161      END;
3162      ----------------------------------------------------------------------------------
3163      -- Scope: compile_constraints
3164      -- Returns TRUE when the given expression has children, otherwise returns FALSE.
3165      FUNCTION expr_has_children ( p_expr_id IN VARCHAR2 ) RETURN BOOLEAN IS
3166      BEGIN
3167         IF ( NOT h_exprid_childrenindex.EXISTS ( p_expr_id )) THEN
3168             RETURN FALSE;
3169         ELSE
3170             RETURN TRUE;
3171         END IF;
3172      END expr_has_children;
3173      ----------------------------------------------------------------------------------
3174      -- Scope: compile_constraints
3175      -- Returns TRUE when the given expression has only one child, otherwise returns FALSE.
3176      FUNCTION expr_has_one_child ( p_expr_id IN VARCHAR2 ) RETURN BOOLEAN IS
3177      BEGIN
3178         IF ( expr_has_children(p_expr_id) AND h_exprid_numberofchildren ( p_expr_id ) = 1) THEN
3179          RETURN TRUE;
3180         ELSE
3181          RETURN FALSE;
3182         END IF;
3183      END expr_has_one_child;
3184      ----------------------------------------------------------------------------------
3185      -- Scope: compile_constraints
3186      -- Returns TRUE when the given expression has only two child, otherwise returns FALSE.
3187      FUNCTION expr_has_two_children ( p_expr_id IN VARCHAR2 ) RETURN BOOLEAN IS
3188      BEGIN
3189         IF ( expr_has_children(p_expr_id) AND h_exprid_numberofchildren ( p_expr_id ) = 2) THEN
3190          RETURN TRUE;
3191         ELSE
3192          RETURN FALSE;
3193         END IF;
3194      END expr_has_two_children;
3195      ----------------------------------------------------------------------------------
3196      -- Scope: compile_constraints
3197      -- Returns the node details (using type_iterator_value structure)
3198      -- associated with the given line index. Returns type_iterator_value.value_type
3199      -- as null when the line index is not referrings to a node.
3200      FUNCTION get_structure_node ( p_index IN PLS_INTEGER ) RETURN type_iterator_value IS
3201 
3202         l_parameter        type_iterator_value;
3203 
3204      BEGIN
3205 
3206         l_parameter.value_type := const_valuetype_unknown;
3207 
3208         IF ( t_exp_exprtype ( p_index ) = h_exprtypes ('node')) THEN
3209 
3210            l_parameter.ps_node_id := t_exp_psnodeid ( p_index );
3211            l_parameter.model_ref_expl_id := t_exp_modelrefexplid ( p_index );
3212 
3213            l_parameter.value_type := const_valuetype_node;
3214 
3215         ELSIF ( t_exp_exprtype ( p_index ) = h_exprtypes ('argument')) THEN
3216 
3217            l_parameter := retrieve_parameter ( t_exp_argumentname ( p_index ));
3218 
3219         END IF;
3220 
3221         IF ( l_parameter.value_type <> const_valuetype_node ) THEN
3222 
3223            l_parameter.value_type := NULL;
3224 
3225         END IF;
3226 
3227         RETURN l_parameter;
3228      END get_structure_node;
3229      ----------------------------------------------------------------------------------
3230      -- Scope: compile_constraints
3231      -- Returns TRUE when the given node has children, otherwise returns FALSE.
3232      FUNCTION node_has_children ( p_node_id IN VARCHAR2 ) RETURN BOOLEAN IS
3233      BEGIN
3234         IF ( h_psnid_lastchildindex.EXISTS ( p_node_id )) THEN
3235           RETURN TRUE;
3236         ELSE
3237           RETURN FALSE;
3238         END IF;
3239      END node_has_children;
3240      ----------------------------------------------------------------------------------
3241      --This function verifies that a node is a port, and returns its target.
3242      -- Scope: compile_constraints
3243      -- Returns the target node id for the given port. Returns NULL when
3244      -- the given id is not a port.
3245      FUNCTION get_port_id ( p_node_id IN VARCHAR2 ) RETURN NUMBER IS
3246        l_index   PLS_INTEGER := h_psnid_backindex ( p_node_id );
3247      BEGIN
3248        IF ( t_psn_detailedtype ( l_index ) IN ( h_psntypes ('reference'), h_psntypes ('connector'))) THEN
3249 
3250            RETURN t_psn_referenceid ( l_index );
3251 
3252        ELSIF ( t_psn_detailedtype ( l_index ) = h_psntypes ('component')) THEN
3253 
3254            RETURN t_psn_psnodeid ( l_index );
3255 
3256        ELSE
3257 
3258           RETURN NULL;
3259        END IF;
3260      END get_port_id;
3261      ----------------------------------------------------------------------------------
3262      --This function is used to explode OptionOf or Options() operation into a table of
3263      --children for boms. Only bom children are included.
3264     -- Scope: compile_constraints
3265      FUNCTION explode_bom_children ( p_node_id        IN NUMBER
3266                                    , p_expl_id        IN NUMBER
3267                                    , p_first_index    IN PLS_INTEGER
3268                                    , p_last_index     IN PLS_INTEGER
3269                                    , p_optional_only  IN BOOLEAN
3270                                    ) RETURN type_iteratornode_table IS
3271 
3272         t_children          type_iteratornode_table;
3273         l_expl_id           VARCHAR2(4000);
3274 
3275         l_index             PLS_INTEGER;
3276         l_count             PLS_INTEGER;
3277 
3278      BEGIN
3279 
3280         l_index := p_first_index;
3281         l_count := 1;
3282 
3283         l_expl_id := TO_CHAR ( p_expl_id );
3284 
3285         WHILE ( l_index <= p_last_index ) LOOP
3286 
3287            IF ( t_psn_parentid ( l_index ) = p_node_id AND is_bom ( l_index ) AND
3288                   ( NOT p_optional_only OR t_psn_bomrequiredflag ( l_index ) = '0' )) THEN
3289 
3290               t_children ( l_count ).expr_index := l_index;
3291               t_children ( l_count ).ps_node_id := t_psn_psnodeid ( l_index );
3292 
3293               IF ( t_psn_psnodetype ( l_index ) IN ( h_psntypes ('reference'), h_psntypes ('connector'))) THEN
3294 
3295                  --If the bom child is a reference, we need to adjust the explosion id to be that
3296                  --of the reference.
3297 
3298                  t_children ( l_count ).model_ref_expl_id := h_parentid_referring_explid ( l_expl_id )( TO_CHAR ( t_psn_psnodeid ( l_index )));
3299 
3300               ELSE
3301 
3302                  t_children ( l_count ).model_ref_expl_id := p_expl_id;
3303 
3304               END IF;
3305 
3306               l_count := l_count + 1;
3307 
3308            END IF;
3309 
3310            l_index := l_index + 1;
3311 
3312         END LOOP;
3313 
3314         IF ( t_children.COUNT = 0 ) THEN
3315 
3316            -- BOM node ^NODE_NAME has no optional selections to participate in rule. Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
3317 
3318            report_and_raise_rule_warning (
3319              CZ_UTILS.GET_TEXT ( CZ_FCE_W_NO_OPTIONAL_CHILDREN,
3320                'NODE_NAME', CZ_FCE_COMPILE_UTILS.GET_NODE_PATH( p_node_id,
3321                           ps_node_id_table_to_string(
3322                                 build_complete_path(p_node_id, p_expl_id) ) ),
3323                'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name ),
3324                'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name )),
3325              'explode_bom_children'
3326             );
3327 
3328         END IF;
3329 
3330         RETURN t_children;
3331      END explode_bom_children;
3332      ----------------------------------------------------------------------------------
3333      --This function is used to explode OptionOf or Options() operation into a table of
3334      --children.
3335      -- Scope: compile_constraints
3336      FUNCTION explode_node_children ( p_node_id IN NUMBER, p_expl_id IN NUMBER, p_optional_only IN BOOLEAN )
3337        RETURN type_iteratornode_table IS
3338 
3339         t_children          type_iteratornode_table;
3340         l_node_id           VARCHAR2(4000);
3341 
3342         l_last_index        PLS_INTEGER;
3343         l_index             PLS_INTEGER;
3344         l_count             PLS_INTEGER;
3345 
3346      BEGIN
3347 
3348         l_node_id := TO_CHAR ( p_node_id );
3349         l_index := h_psnid_backindex ( l_node_id );
3350 
3351         IF ( is_bom_port ( l_index )) THEN
3352 
3353            l_node_id := TO_CHAR ( t_psn_referenceid ( l_index ));
3354            l_index := h_psnid_backindex ( l_node_id );
3355 
3356         END IF;
3357 
3358         --  Node ^NODE_NAME has no children.  Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
3359 
3360         IF ( node_has_children ( l_node_id )) THEN
3361 
3362           l_last_index := h_psnid_lastchildindex ( l_node_id );
3363 
3364         ELSE
3365 
3366           -- Node ^NODE_NAME has no children.  Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
3367 
3368           report_and_raise_rule_warning (
3369               p_text => CZ_UTILS.GET_TEXT( CZ_FCE_W_NODE_MUST_HAVE_CHILD,
3370                         'NODE_NAME', CZ_FCE_COMPILE_UTILS.GET_NODE_PATH( p_node_id,
3371                           ps_node_id_table_to_string(
3372                                 build_complete_path(p_node_id, p_expl_id) ) ),
3373                         'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name ),
3374                         'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH ( p_component_id, p_model_path)
3375                         ),
3376               p_warning_location => 'explode_node_children');
3377 
3378         END IF;
3379 
3380         IF ( is_bom_node ( l_index )) THEN
3381 
3382            t_children := explode_bom_children ( l_node_id, p_expl_id, l_index + 1, l_last_index, p_optional_only );
3383 
3384         ELSE
3385 
3386            --If this is non-bom, the operation can only be performed on an option feature.
3387            --Options always follow the feature and there can be no tokens among them. The
3388            --explosion is always that of the feature.
3389 
3390            l_index := l_index + 1;
3391            l_count := 1;
3392 
3393            WHILE ( l_index <= l_last_index ) LOOP
3394 
3395               t_children ( l_count ).expr_index := l_index;
3396               t_children ( l_count ).ps_node_id := t_psn_psnodeid ( l_index );
3397               t_children ( l_count ).model_ref_expl_id := p_expl_id;
3398 
3399               l_count := l_count + 1;
3400               l_index := l_index + 1;
3401 
3402            END LOOP;
3403         END IF;
3404 
3405         RETURN t_children;
3406      END explode_node_children;
3407 ---------------------------------------------------------------------------------------
3408      --p_type is either 'ISingletonExprDef', 'IInstanceQuantifier' or 'IPortExprDef'.
3409      --It can also be NULL if the variable is local.
3410      -- Scope: compile_constraints
3411      PROCEDURE push_variable ( p_id IN NUMBER, p_type IN VARCHAR2 ) IS
3412 
3413        l_id   VARCHAR2(4000) := TO_CHAR ( p_id );
3414 
3415      BEGIN
3416 
3417         --This procedure can be called on a Bom Model, when a reference to this model
3418         --participates in rules.
3419 
3420         IF ( h_psnid_psnodetype ( l_id ) = h_psntypes ('bommodel')) THEN RETURN; END IF;
3421 
3422         IF ( h_psnid_devlprojectid ( l_id ) = p_component_id ) THEN
3423 
3424            --This is a local variable, we can just retrieve it from the local hash.
3425 
3426            haload_object ( p_id , 1 );
3427 
3428         ELSE
3429 
3430            --This is a remote variable. Need to duplicate parent's object on the stack
3431            --to be used for the call to getType().
3432 
3433            emit_dup ();
3434            emit_invokevirtual ( p_type || '.getType()');
3435            push_variable_name ( p_id );
3436            emit_invokevirtual ('IModelDef.getVar(String)');
3437 
3438         END IF;
3439      END push_variable;
3440      ----------------------------------------------------------------------------------
3441      --This function splits the '_'-separated path of ps_node_id(s) into a number table.
3442      -- Scope: compile_constraints
3443      FUNCTION split_path ( p_path IN VARCHAR2 ) RETURN type_number_table IS
3444 
3445        l_substr      VARCHAR2(32000) := p_path;
3446        l_index       PLS_INTEGER;
3447        l_return_tbl  type_number_table;
3448 
3449      BEGIN
3450 
3451        IF ( l_substr IS NULL )THEN RETURN l_return_tbl; END IF;
3452 
3453        LOOP
3454 
3455           l_index := INSTR ( l_substr, '_', -1 );
3456 
3457           IF ( l_index > 0 ) THEN
3458 
3459              l_return_tbl ( l_return_tbl.COUNT + 1 ) := TO_NUMBER ( SUBSTR ( l_substr, l_index + 1 ));
3460              l_substr := SUBSTR (l_substr, 1, l_index - 1 );
3461 
3462           ELSE
3463 
3464              l_return_tbl (l_return_tbl.COUNT + 1 ) := TO_NUMBER ( l_substr );
3465              EXIT;
3466 
3467           END IF;
3468        END LOOP;
3469 
3470        RETURN l_return_tbl;
3471      END split_path;
3472 ---------------------------------------------------------------------------------------
3473      FUNCTION split_str_path ( p_path IN VARCHAR2 ) RETURN type_varchar4000_table IS
3474 
3475        l_substr      VARCHAR2(32000) := p_path;
3476        l_index       PLS_INTEGER;
3477        l_return_tbl  type_varchar4000_table;
3478 
3479      BEGIN
3480 
3481        IF ( p_path IS NULL ) THEN RETURN l_return_tbl; END IF;
3482 
3483        LOOP
3484 
3485          l_index := INSTR ( l_substr, FND_GLOBAL.LOCAL_CHR ( 7 ));
3486 
3487          IF( l_index > 0 )THEN
3488 
3489            l_return_tbl (l_return_tbl.COUNT + 1 ) := SUBSTR ( l_substr, 1, l_index - 1 );
3490            l_substr := SUBSTR( l_substr, l_index + 1 );
3491 
3492          ELSE
3493 
3494            l_return_tbl (l_return_tbl.COUNT + 1 ) := l_substr;
3495            EXIT;
3496 
3497          END IF;
3498        END LOOP;
3499 
3500        RETURN l_return_tbl;
3501 
3502      END split_str_path;
3503 ---------------------------------------------------------------------------------------
3504      -- Scope: compile_constraints
3505      FUNCTION generate_path ( p_complete_path IN type_number_table
3506                             , p_input_context IN expression_context
3507                             , x_output_context IN OUT NOCOPY expression_context
3508                             ) RETURN PLS_INTEGER IS
3509 
3510         tl_target_path       type_number_table;
3511 
3512         l_count              PLS_INTEGER;
3513         l_quantifier_index   PLS_INTEGER;
3514         l_instances_index    PLS_INTEGER;
3515         l_target_index       PLS_INTEGER;
3516         l_contrib_index      PLS_INTEGER;
3517         l_singleton_count    PLS_INTEGER;
3518         l_acc_count          PLS_INTEGER;
3519         l_target_count       PLS_INTEGER;
3520 
3521         l_key                VARCHAR2(4000);
3522         l_return             PLS_INTEGER := const_no_instances;
3523 
3524      BEGIN
3525 
3526         IF ( p_input_context.context_type = const_context_target ) THEN
3527 
3528            l_target_count := t_acc_targets.COUNT;
3529 
3530         END IF;
3531 
3532         --Find the most shallow port, it's instancesOf should be called on IModelDef.
3533 
3534         l_count := p_complete_path.COUNT;
3535         l_instances_index := l_count;
3536 
3537         WHILE ( l_instances_index > 0 AND h_psnid_detailedtype ( p_complete_path ( l_instances_index )) NOT IN
3538                  ( h_psntypes ('component'), h_psntypes ('reference'), h_psntypes ('connector'))) LOOP
3539 
3540             l_instances_index := l_instances_index - 1;
3541 
3542         END LOOP;
3543 
3544         IF ( l_instances_index <= l_count AND l_instances_index > 1 ) THEN
3545 
3546            --We count the number of node participants in the contributor expression which are
3547            --under ports for validation. Participant itself can be the only port in the path,
3548            --this is allowed (l_instances_index > 1)
3549 
3550            contributor_validation := contributor_validation + 1;
3551 
3552         END IF;
3553 
3554         IF ( p_input_context.context_type = const_context_contributor ) THEN
3555 
3556            --We are generating an accumulation contributor. Need to find the LCA with the target's path,
3557            --because this will be the instance quantifier. Below this node we will generate hierarchical
3558            --unions.
3559 
3560            --The target for this contributor is the last element in the array of target.
3561 
3562            l_target_count := p_input_context.context_num_data;
3563            tl_target_path := t_acc_complete_path ( l_target_count );
3564 
3565            --Find the LCA.
3566 
3567            l_target_index := tl_target_path.COUNT;
3568            l_contrib_index := l_count;
3569            l_quantifier_index := l_contrib_index + 1;
3570 
3571            IF ( l_target_index > 0 ) THEN
3572 
3573               WHILE ( l_target_index > 0 AND l_contrib_index > 0 AND
3574                            tl_target_path ( l_target_index ) = p_complete_path ( l_contrib_index )) LOOP
3575 
3576                  IF ( h_psnid_detailedtype ( p_complete_path ( l_contrib_index )) IN
3577                             ( h_psntypes ('component'), h_psntypes ('reference'), h_psntypes ('connector'))) THEN
3578 
3579                     l_quantifier_index := l_contrib_index;
3580 
3581                  END IF;
3582 
3583                  l_target_index := l_target_index - 1;
3584                  l_contrib_index := l_contrib_index - 1;
3585 
3586               END LOOP;
3587            END IF;
3588 
3589         ELSE
3590 
3591            --Find the deepest port, this will be the instance quantifier to use in forAll.
3592 
3593            l_quantifier_index := 2;
3594 
3595            --#<important>
3596            --Using h_psnid_detailedtype is very essential here and in the next block. If any changes are made
3597            --to the definition of h_psnid_detailedtype array, this code may need to change.
3598 
3599            WHILE ( l_quantifier_index <= l_count AND h_psnid_detailedtype ( p_complete_path ( l_quantifier_index )) NOT IN
3600                     (h_psntypes ('component'), h_psntypes ('reference'), h_psntypes ('connector'))) LOOP
3601 
3602                l_quantifier_index := l_quantifier_index + 1;
3603 
3604            END LOOP;
3605         END IF;
3606 
3607         IF ( l_instances_index > 1 AND l_instances_index >= l_quantifier_index AND
3608              NVL ( p_input_context.context_type, const_context_generic ) <> const_context_aggregatesum ) THEN
3609 
3610            --There is a port variable in the path, and it is not the variable itself (l_instances_index > 1),
3611            --so we will have to call instancesOf on IModelDef.
3612 
3613            aload_model_def ( p_component_id );
3614 
3615         END IF;
3616 
3617         push_variable ( p_complete_path ( l_count ), NULL );
3618         l_key := TO_CHAR ( p_complete_path ( l_count ));
3619 
3620         l_singleton_count := 0;
3621 
3622         FOR i IN REVERSE 1..l_count - 1 LOOP
3623 
3624            --(need to include 'bommodel' below to support rare cases of old upgraded models, bug #6613028).
3625 
3626            IF ( h_psnid_detailedtype ( p_complete_path ( i + 1 )) IN ( h_psntypes ('singleton'), h_psntypes ('bomoptionclass'), h_psntypes ('bommodel'))) THEN
3627 
3628               l_singleton_count := l_singleton_count + 1;
3629 
3630               push_variable ( p_complete_path ( i ), 'ISingletonExprDef');
3631               emit_invokevirtual ('ISingletonExprDef.getVarRef(IExprDef)');
3632 
3633            ELSIF ( h_psnid_detailedtype ( p_complete_path ( i + 1 )) IN ( h_psntypes ('component'), h_psntypes ('reference'), h_psntypes ('connector'))) THEN
3634 
3635               IF ( p_input_context.context_type = const_context_aggregatesum ) THEN
3636 
3637                  IF ( i + 1 < l_instances_index ) THEN
3638 
3639                     emit_invokevirtual('IPortExprDef.hierarchicalUnion(IPortExprDef)');
3640 
3641                  END IF;
3642 
3643                  push_variable ( p_complete_path ( i ), 'IPortExprDef');
3644                  l_return := const_resourcesum_required;
3645 
3646               ELSE
3647 
3648                  IF ( i + 1 = l_instances_index ) THEN
3649 
3650                     --For the most shallow port down the path need to use this signature.
3651 
3652                     IF ( l_instances_index >= l_quantifier_index ) THEN
3653 
3654                        --This condition is required for contributors, because in this case first component
3655                        --does not necessarily need instancesOf.
3656 
3657                        emit_invokevirtual('IModelDef.instancesOf(IPortExprDef)');
3658 
3659                     END IF;
3660 
3661                  ELSIF ( i + 1 >= l_quantifier_index ) THEN
3662 
3663                     --We are still above the deepest port.
3664 
3665                     emit_invokevirtual('IInstanceQuantifier.instancesOf(IPortExprDef)');
3666 
3667                  END IF;
3668 
3669                  IF ( i + 1 = l_quantifier_index ) THEN
3670 
3671                     --We need to collect only distinct instance quantifiers.
3672 
3673                     IF ( p_input_context.context_type IN ( const_context_contributor, const_context_target)) THEN
3674 
3675                        t_acc_local_quantifiers ( t_acc_local_quantifiers.COUNT + 1 ) := l_key;
3676 
3677                        IF ( NOT h_acc_quantifiers ( l_target_count ).EXISTS ( l_key )) THEN
3678 
3679                            l_acc_count := t_acc_quantifiers ( l_target_count ).COUNT + 1;
3680 
3681                            t_acc_quantifiers ( l_target_count )( l_acc_count ) := l_key;
3682                            h_acc_quantifiers ( l_target_count )( l_key ) := 1;
3683 
3684                            copyto_register ( l_key );
3685 
3686                        END IF;
3687 
3688                     ELSE
3689 
3690                        IF ( NOT h_instancequantifiers.EXISTS ( l_key )) THEN
3691 
3692                            t_instancequantifiers ( t_instancequantifiers.COUNT + 1 ) := l_key;
3693                            h_instancequantifiers ( l_key ) := 1;
3694 
3695                            copyto_local_variable ( l_key );
3696 
3697                        END IF;
3698                     END IF;
3699 
3700                     l_return := const_quantifier_created;
3701 
3702                  END IF;
3703 
3704                  --Note that if we are below the path's instance quantifier (i + 1 < l_quantifier_index)
3705                  --and still are on a port, we are generating a contributor, because for a regular node
3706                  --path's instance quantifier will be on the deepest port.
3707 
3708                  l_contrib_index := i + 2 + l_singleton_count;
3709 
3710                  IF ( l_return = const_quantifier_created AND l_contrib_index = l_quantifier_index ) THEN
3711 
3712                     emit_invokevirtual('IInstanceQuantifier.getExprFromInstance(IExprDef)');
3713 
3714                  END IF;
3715 
3716                  IF ( l_contrib_index < l_quantifier_index ) THEN
3717 
3718                     emit_invokevirtual('IPortExprDef.hierarchicalUnion(IPortExprDef)');
3719                     push_variable ( p_complete_path ( i ), 'IPortExprDef');
3720 
3721                     l_return := const_resourcesum_required;
3722 
3723                  ELSIF ( l_contrib_index = l_quantifier_index ) THEN
3724 
3725                     push_variable ( p_complete_path ( i ), 'IPortExprDef');
3726                     l_return := const_resourcesum_required;
3727 
3728                  ELSE
3729 
3730                     push_variable ( p_complete_path ( i ), 'IInstanceQuantifier');
3731 
3732                  END IF;
3733               END IF;
3734 
3735               l_singleton_count := 0;
3736 
3737            END IF;
3738 
3739            l_key := l_key || '_' || TO_CHAR ( p_complete_path ( i ));
3740 
3741         END LOOP;
3742 
3743         IF ( p_input_context.context_type = const_context_aggregatesum ) THEN
3744           IF ( h_psnid_detailedtype ( p_complete_path ( 1 )) IN ( h_psntypes ('component'), h_psntypes ('reference'), h_psntypes ('connector'))) THEN
3745 
3746              IF ( l_instances_index > 1 ) THEN
3747 
3748                 emit_invokevirtual('IPortExprDef.hierarchicalUnion(IPortExprDef)');
3749 
3750              END IF;
3751 
3752              l_return := const_resourcesum_required;
3753 
3754           END IF;
3755         END IF;
3756 
3757         RETURN l_return;
3758      END generate_path;
3759      ----------------------------------------------------------------------------------
3760      -- Scope: compile_constraints
3761      FUNCTION generate_path ( p_node_id IN NUMBER
3762                             , p_expl_id IN NUMBER
3763                             , p_input_context IN expression_context
3764                             , x_output_context IN OUT NOCOPY expression_context
3765                             ) RETURN PLS_INTEGER IS
3766 
3767         l_target_key         VARCHAR2(4000);
3768         l_target_count       PLS_INTEGER;
3769 
3770         l_acc_init           type_varchar4000_table;
3771         h_acc_init           type_data_hashtable;
3772         tl_complete_path     type_number_table;
3773 
3774      BEGIN
3775 
3776         IF ( p_input_context.context_type = const_context_target ) THEN
3777 
3778            --In general, this key should contain more information about the target,
3779            --such as properties, applied to the target.
3780 
3781            l_target_key := TO_CHAR ( p_node_id ) || ':' || TO_CHAR ( p_expl_id );
3782 
3783            x_output_context.context_type := const_context_target;
3784            x_output_context.context_data := l_target_key;
3785 
3786            t_acc_target_sequence ( t_acc_targets.COUNT + 1 ) := 0;
3787            t_acc_targets ( t_acc_targets.COUNT + 1 ) := l_target_key;
3788 
3789            l_target_count := t_acc_targets.COUNT;
3790 
3791            h_acc_targets ( l_target_key ) := l_target_count;
3792            t_acc_quantifiers ( l_target_count ) := l_acc_init;
3793            h_acc_quantifiers ( l_target_count ) := h_acc_init;
3794 
3795            x_output_context.context_num_data := l_target_count;
3796 
3797         END IF;
3798 
3799         tl_complete_path := build_complete_path ( p_node_id, p_expl_id );
3800 
3801         IF ( p_input_context.context_type = const_context_target ) THEN
3802 
3803           t_acc_complete_path ( l_target_count ) := tl_complete_path;
3804 
3805         END IF;
3806 
3807         IF ( tl_complete_path.COUNT = 0 ) THEN RETURN const_no_instances; END IF;
3808 
3809         RETURN generate_path ( tl_complete_path, p_input_context, x_output_context );
3810 
3811      END generate_path;
3812      ----------------------------------------------------------------------------------
3813      -- Scope: compile_constraints
3814      PROCEDURE generate_quantifier ( p_key IN VARCHAR2 ) IS
3815 
3816         tl_complete_path    type_number_table;
3817         l_count             PLS_INTEGER;
3818 
3819         l_instancesOf       VARCHAR2(4000);
3820 
3821      BEGIN
3822 
3823         tl_complete_path := split_path ( p_key );
3824         l_count := tl_complete_path.COUNT;
3825 
3826         IF ( l_count = 0 ) THEN RETURN; END IF;
3827 
3828         l_instancesOf := 'IModelDef.instancesOf(IPortExprDef)';
3829 
3830         aload_model_def ( p_component_id );
3831         push_variable ( tl_complete_path ( l_count ), NULL );
3832 
3833         FOR i IN REVERSE 1..l_count - 1 LOOP
3834 
3835            IF ( h_psnid_detailedtype ( tl_complete_path ( i + 1 )) IN ( h_psntypes ('singleton'), h_psntypes ('bomoptionclass'))) THEN
3836 
3837               push_variable ( tl_complete_path ( i ), 'ISingletonExprDef');
3838               emit_invokevirtual ('ISingletonExprDef.getVarRef(IExprDef)');
3839 
3840            ELSE --(h_psntypes ('component'), h_psntypes ('reference'), h_psntypes ('connector'))
3841 
3842               emit_invokevirtual( l_instancesOf );
3843               l_instancesOf := 'IInstanceQuantifier.instancesOf(IPortExprDef)';
3844 
3845               push_variable ( tl_complete_path ( i ), 'IInstanceQuantifier');
3846 
3847            END IF;
3848         END LOOP;
3849 
3850         emit_invokevirtual( l_instancesOf );
3851         copyto_local_variable ( p_key );
3852 
3853      END generate_quantifier;
3854      ----------------------------------------------------------------------------------
3855      -- Scope: compile_constraints
3856      PROCEDURE aload_quantifier ( p_key IN VARCHAR2 ) IS
3857      BEGIN
3858 
3859         IF ( NOT local_variable_defined ( p_key )) THEN
3860 
3861            generate_quantifier ( p_key );
3862 
3863         ELSE
3864 
3865            aload_local_variable ( p_key );
3866 
3867         END IF;
3868      END aload_quantifier;
3869      ----------------------------------------------------------------------------------
3870      -- Scope: compile_constraints
3871      PROCEDURE apply_bom_property ( p_property IN VARCHAR2 ) IS
3872      BEGIN
3873 
3874          emit_dup ();
3875          emit_invokevirtual ('ISingletonExprDef.getType()');
3876          emit_invokevirtual ( p_property );
3877          emit_invokevirtual ('ISingletonExprDef.getVarRef(IExprDef)');
3878 
3879      END apply_bom_property;
3880      ----------------------------------------------------------------------------------
3881      PROCEDURE any_option_selected IS
3882      BEGIN
3883 
3884         emit_invokevirtual ('ISetExprDef.card()');
3885         push_integer_constant ( 0 );
3886         emit_invokevirtual('INumExprDef.gt(int)');
3887 
3888      END any_option_selected;
3889      ----------------------------------------------------------------------------------
3890      -- Scope: compile_constraints
3891      PROCEDURE all_options_selected ( p_card IN PLS_INTEGER ) IS
3892      BEGIN
3893 
3894         emit_invokevirtual ('ISetExprDef.card()');
3895         push_integer_constant ( p_card );
3896         emit_invokevirtual('INumExprDef.eq(int)');
3897 
3898      END all_options_selected;
3899      ----------------------------------------------------------------------------------
3900      -- Scope: compile_constraints
3901      FUNCTION get_context_type ( j IN PLS_INTEGER ) RETURN PLS_INTEGER IS
3902 
3903         l_index      PLS_INTEGER;
3904 
3905      BEGIN
3906 
3907         l_index := h_exprid_backindex ( TO_CHAR ( t_exp_exprparentid ( j )));
3908 
3909         CASE t_exp_exprtype ( l_index ) WHEN h_exprtypes ('operator') THEN
3910 
3911           IF ( t_exp_templateid ( l_index ) IN (
3912                     h_templates ('and')
3913                   , h_templates ('or')
3914                   , h_templates ('not')
3915                   )) THEN
3916 
3917               RETURN h_datatypes ('boolean');
3918 
3919           ELSIF ( t_exp_templateid ( l_index ) IN (
3920                     h_templates ('equals')
3921                   , h_templates ('notequals')
3922                   , h_templates ('gt')
3923                   , h_templates ('lt')
3924                   , h_templates ('ge')
3925                   , h_templates ('le')
3926                   , h_templates ('add')
3927                   , h_templates ('subtract')
3928                   , h_templates ('multiply')
3929                   , h_templates ('div')
3930                   , h_templates ('neg')
3931                   , h_templates ('totext')
3932                   )) THEN
3933 
3934               --Note, that ToText operator means numeric context for its argument. That means that ToText
3935               --cannot be applied to a text argument. May need to change if this is a problem.
3936 
3937               RETURN h_datatypes ('decimal');
3938 
3939           ELSIF ( t_exp_templateid ( l_index ) IN (
3940                     h_templates ('doesnotbeginwith')
3941                   , h_templates ('doesnotendwith')
3942                   , h_templates ('doesnotcontain')
3943                   , h_templates ('notlike')
3944                   , h_templates ('concatenate')
3945                   , h_templates ('beginswith')
3946                   , h_templates ('endswith')
3947                   , h_templates ('contains')
3948                   , h_templates ('like')
3949                   , h_templates ('matches')
3950                   , h_templates('textequals')
3951                   , h_templates('textnotequals')
3952                   )) THEN
3953 
3954               RETURN h_datatypes ('text');
3955 
3956            ELSE
3957               -- 'Unknown operator type "^OPERTYPE" in the rule. Rule "^RULE_NAME" in the Model ^MODEL_NAME" ignored.';
3958               report_and_raise_rule_sys_warn(
3959                 GET_NOT_TRANSLATED_TEXT(CZ_FCE_SW_UNKNOWN_OP_TYPE,
3960                   'OPERTYPE',  TO_CHAR(t_exp_templateid ( j ))),
3961                 'get_context_type'
3962                );
3963               RETURN NULL;
3964            END IF;
3965 
3966         ELSE
3967            -- 'Unable to get context data type for expression node with the id "^EXPR_ID". Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
3968            report_and_raise_rule_sys_warn(
3969                 p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_RE_ENODE_NO_DTYPE,
3970                         'EXPR_ID', l_index),
3971                 p_warning_location => 'get_context_type');
3972            RETURN NULL;
3973 
3974         END CASE;
3975      END get_context_type;
3976      ----------------------------------------------------------------------------------
3977      -- Scope: compile_constraints
3978      FUNCTION logical_context ( j IN PLS_INTEGER, p_context_type IN PLS_INTEGER ) RETURN BOOLEAN IS
3979 
3980         l_parent_id  VARCHAR2(4000);
3981         l_child      PLS_INTEGER;
3982         l_index      PLS_INTEGER;
3983 
3984      BEGIN
3985 
3986         IF ( p_context_type = const_context_logical ) THEN RETURN TRUE; END IF;
3987 
3988         l_parent_id := TO_CHAR ( t_exp_exprparentid ( j ));
3989         IF ( l_parent_id IS NULL ) THEN RETURN FALSE; END IF;
3990 
3991         l_index := h_exprid_backindex ( l_parent_id );
3992 
3993         IF ( h_logical_ops.EXISTS ( t_exp_templateid ( l_index ))) THEN RETURN TRUE; END IF;
3994 
3995         --Bug #7026587. Check the special case when the other operand of equality operator is a boolean literal.
3996 
3997         IF ( t_exp_templateid ( l_index ) IN ( h_templates ('equals'), h_templates ('notequals'))) THEN
3998 
3999            l_child := h_exprid_childrenindex ( l_parent_id );
4000            IF ( l_child = j ) THEN l_child := l_child + 1; END IF;
4001 
4002            IF ( t_exp_exprtype ( l_child ) = h_exprtypes ('literal') AND t_exp_datatype ( l_child ) = h_datatypes ('boolean')) THEN
4003 
4004               RETURN TRUE;
4005 
4006            END IF;
4007         END IF;
4008 
4009         RETURN FALSE;
4010      END logical_context;
4011      ----------------------------------------------------------------------------------
4012      -- Scope: compile_constraints
4013      FUNCTION numeric_context ( j IN PLS_INTEGER, p_context_type IN PLS_INTEGER ) RETURN BOOLEAN IS
4014 
4015         l_parent_id  VARCHAR2(4000);
4016         l_child      PLS_INTEGER;
4017         l_index      PLS_INTEGER;
4018 
4019      BEGIN
4020 
4021         IF ( p_context_type IN ( const_context_numeric, const_context_contributor, const_context_target, const_context_aggregatesum )) THEN
4022 
4023            RETURN TRUE;
4024 
4025         END IF;
4026 
4027         l_parent_id := TO_CHAR ( t_exp_exprparentid ( j ));
4028         IF ( l_parent_id IS NULL ) THEN RETURN FALSE; END IF;
4029 
4030         l_index := h_exprid_backindex ( l_parent_id );
4031 
4032         IF (NOT h_numeric_ops.EXISTS ( t_exp_templateid ( l_index ))) THEN RETURN FALSE; END IF;
4033 
4034         --Bug #7026587. Check the special case when the other operand of equality operator is a boolean literal.
4035 
4036         IF ( t_exp_templateid ( l_index ) IN ( h_templates ('equals'), h_templates ('notequals'))) THEN
4037 
4038            l_child := h_exprid_childrenindex ( l_parent_id );
4039            IF ( l_child = j ) THEN l_child := l_child + 1; END IF;
4040 
4041            IF ( t_exp_exprtype ( l_child ) = h_exprtypes ('literal') AND t_exp_datatype ( l_child ) = h_datatypes ('boolean')) THEN
4042 
4043               RETURN FALSE;
4044 
4045            END IF;
4046         END IF;
4047 
4048         RETURN TRUE;
4049      END numeric_context;
4050      ----------------------------------------------------------------------------------
4051      -- Scope: compile_constraints
4052      PROCEDURE apply_bom_logical_context ( p_node_id IN NUMBER, p_instances IN PLS_INTEGER ) IS
4053 
4054         l_type      NUMBER;
4055 
4056      BEGIN
4057 
4058         l_type := h_psnid_detailedtype ( TO_CHAR ( p_node_id ));
4059 
4060         IF ( l_type IN ( h_psntypes ('bomoptionclass'), h_psntypes ('bomstandard'))) THEN
4061 
4062             apply_bom_property ('IBomDef.selected()');
4063             IF ( p_instances = const_quantifier_created ) THEN emit_invokevirtual('IInstanceQuantifier.getExprFromInstance(IExprDef)'); END IF;
4064 
4065         ELSIF ( l_type IN ( h_psntypes ('reference'), h_psntypes ('connector'))) THEN
4066 
4067             IF ( p_instances = const_quantifier_created ) THEN emit_invokevirtual('IInstanceQuantifier.getExprFromInstance(IExprDef)'); END IF;
4068 
4069             emit_invokevirtual ('IPortExprDef.card()');
4070             push_integer_constant ( 0 );
4071             emit_invokevirtual('INumExprDef.gt(int)');
4072 
4073         ELSE
4074 
4075             --#<should never happen>
4076             -- 'Type ^TYPE is not a known BOM child node type. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
4077             report_and_raise_rule_sys_warn(
4078                p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_BOM_INVAL_CHILD_TYP,
4079                             'TYPE', l_type ),
4080                p_warning_location => 'apply_bom_logical_context');
4081 
4082         END IF;
4083      END apply_bom_logical_context;
4084      ----------------------------------------------------------------------------------
4085      -- Scope: compile_constraints
4086      PROCEDURE apply_logical_context ( p_node_id IN NUMBER, p_context_type IN PLS_INTEGER ) IS
4087 
4088         l_type      NUMBER;
4089 
4090      BEGIN
4091 
4092         l_type := h_psnid_detailedtype ( TO_CHAR ( p_node_id ));
4093 
4094         IF ( l_type IN ( h_psntypes ('bomoptionclass'), h_psntypes ('bomstandard'))) THEN
4095 
4096             apply_bom_property ('IBomDef.selected()');
4097 
4098         ELSIF ( l_type = h_psntypes ('bommodel')) THEN
4099 
4100             IF ( p_node_id <> p_component_id ) THEN
4101 
4102                --Bug #6779671. This call is required only if the property is not applied to the root bom model itself.
4103 
4104                emit_dup ();
4105                emit_invokevirtual ('IInstanceQuantifier.getType()');
4106 
4107             ELSE
4108 
4109                aload_model_def ( p_node_id );
4110 
4111             END IF;
4112 
4113             emit_invokevirtual ('IBomDef.selected()');
4114 
4115         ELSIF ( l_type = h_psntypes ('optionfeature')) THEN
4116 
4117             any_option_selected ();
4118 
4119         ELSIF ( l_type IN ( h_psntypes ('reference'), h_psntypes ('connector'))) THEN
4120 
4121             emit_invokevirtual ('IPortExprDef.card()');
4122             push_integer_constant ( 0 );
4123             emit_invokevirtual('INumExprDef.gt(int)');
4124 
4125         ELSIF ( l_type = h_psntypes ('integerfeature')) THEN
4126 
4127             push_integer_constant ( 0 );
4128             emit_invokevirtual('INumExprDef.gt(int)');
4129 
4130         ELSIF ( l_type = h_psntypes ('option')) THEN
4131 
4132             push_variable_name ( p_node_id );
4133 
4134             IF ( p_context_type = const_context_contributor ) THEN
4135 
4136                emit_invokevirtual ('ISetExprDef.elementCount(Object)');
4137 
4138             ELSE
4139 
4140                emit_invokevirtual ('ISetExprDef.contains(Object)');
4141 
4142             END IF;
4143         END IF;
4144      END apply_logical_context;
4145      ----------------------------------------------------------------------------------
4146      -- Scope: compile_constraints
4147      PROCEDURE apply_numeric_context ( p_node_id IN NUMBER, p_context_type IN PLS_INTEGER ) IS
4148 
4149         l_node_id   VARCHAR2(4000);
4150         l_index     PLS_INTEGER;
4151         l_type      NUMBER;
4152 
4153      BEGIN
4154 
4155         l_node_id := TO_CHAR ( p_node_id );
4156 
4157         l_type := h_psnid_detailedtype ( l_node_id );
4158         l_index := h_psnid_backindex ( l_node_id );
4159 
4160         IF ( l_type IN ( h_psntypes ('bomoptionclass'), h_psntypes ('bomstandard'))) THEN
4161 
4162            apply_bom_property ('IBomDef.absQty()');
4163 
4164         ELSIF ( l_type = h_psntypes ('bommodel')) THEN
4165 
4166            IF ( p_node_id <> p_component_id ) THEN
4167 
4168               --Bug #6779671. This call is required only if the property is not applied to the root bom model itself.
4169 
4170               emit_dup ();
4171               emit_invokevirtual ('IInstanceQuantifier.getType()');
4172 
4173            ELSE
4174 
4175               aload_model_def ( p_node_id );
4176 
4177            END IF;
4178 
4179            emit_invokevirtual ('IBomDef.absQty()');
4180 
4181         ELSIF ( l_type IN ( h_psntypes ('reference'), h_psntypes ('connector'))) THEN
4182 
4183            emit_invokevirtual ('IPortExprDef.card()');
4184 
4185         ELSIF ( l_type = h_psntypes ('optionfeature')) THEN
4186 
4187            emit_invokevirtual ('ISetExprDef.card()');
4188 
4189         ELSIF ( l_type = h_psntypes ('option')) THEN
4190 
4191            --Solver has introduced a new method that can be used in numeric context
4192            --for options universally (Re: bug #6733300).
4193 
4194            push_variable_name ( l_node_id );
4195            emit_invokevirtual ('ISetExprDef.elementCount(Object)');
4196 
4197         END IF;
4198      END apply_numeric_context;
4199      ----------------------------------------------------------------------------------
4200      -- Scope: compile_constraints
4201      PROCEDURE apply_system_property ( p_template_id IN NUMBER
4202                                      , p_index IN NUMBER
4203                                      , p_input_context IN expression_context
4204                                      ) IS
4205 
4206         l_is_bom            BOOLEAN;
4207         l_is_bomreference   BOOLEAN;
4208 
4209         l_return            NUMBER;
4210 
4211      BEGIN
4212 
4213         l_is_bom := is_bom_node ( p_index );
4214         l_is_bomreference := is_bom_port ( p_index );
4215 
4216         IF ( p_template_id = h_templates ('state')) THEN
4217 
4218            apply_logical_context ( t_psn_psnodeid ( p_index ), p_input_context.context_type);
4219 
4220         ELSIF ( h_quantities.EXISTS ( p_template_id ) OR p_template_id = h_templates ('selectioncount')) THEN
4221 
4222            IF ( l_is_bom or l_is_bomreference ) THEN
4223 
4224                IF ( t_psn_psnodetype ( p_index ) <> h_psntypes ('bommodel')) THEN
4225 
4226                  --This call is required only if the property is not applied to the root bom model itself.
4227                  --If the property cannot be applied to the root model, this condition can be removed.
4228 
4229                  emit_dup ();
4230 
4231                  IF ( l_is_bom ) THEN
4232 
4233                     emit_invokevirtual ('ISingletonExprDef.getType()');
4234 
4235                  ELSE
4236 
4237                     IF ( p_input_context.context_type = const_context_contributor ) THEN
4238 
4239                        emit_invokevirtual ( 'IPortExprDef.getType()');
4240 
4241                     ELSE
4242 
4243                        emit_invokevirtual ( 'IInstanceQuantifier.getType()');
4244 
4245                     END IF;
4246                  END IF;
4247 
4248                ELSE
4249 
4250                   aload_model_def ( t_psn_psnodeid ( p_index ));
4251 
4252                END IF;
4253 
4254                IF ( h_quantities.EXISTS ( p_template_id )) THEN
4255 
4256                   emit_invokevirtual ( h_quantities ( p_template_id ));
4257 
4258                ELSE
4259 
4260                   --This is selectionCount property.
4261 
4262                   emit_invokevirtual ('IBomDef.getOCCardSet()');
4263                   emit_invokevirtual ('ISetExprDef.card()');
4264 
4265                END IF;
4266 
4267            ELSE
4268 
4269                IF ( t_psn_detailedtype ( p_index ) = h_psntypes ('optionfeature')) THEN
4270 
4271                   IF ( p_template_id = h_templates ('selectioncount') AND t_psn_countedoptionsflag ( p_index ) = '1' ) THEN
4272 
4273                      --Property is applied to a Counted Option Feature.
4274 
4275                      emit_invokevirtual ('IBagExprDef.count()');
4276 
4277                   ELSE
4278 
4279                      emit_invokevirtual ('ISetExprDef.card()');
4280 
4281                   END IF;
4282 
4283                ELSIF ( t_psn_detailedtype ( p_index ) = h_psntypes ('option')) THEN
4284 
4285                   --This is the same code as in apply_numeric_context to an option. The procedure
4286                   --is not used here because it checks whether the node is bom, and this has been
4287                   --done already at this point.
4288 
4289                   push_variable_name ( TO_CHAR ( t_psn_psnodeid ( p_index )));
4290                   emit_invokevirtual ('ISetExprDef.elementCount(Object)');
4291 
4292                END IF;
4293            END IF;
4294 
4295         ELSIF ( p_template_id = h_templates ('instancecount')) THEN
4296 
4297            -- Property ^PROP_NAME is only applicable to nodes that can contain instances. Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
4298 
4299            l_return := get_port_id ( TO_CHAR ( t_psn_psnodeid ( p_index )));
4300 
4301            IF ( l_return IS NULL ) THEN
4302 
4303              report_and_raise_rule_warning (
4304                 p_text => CZ_UTILS.GET_TEXT(
4305                     CZ_FCE_W_PROP_ONLY_ICOMP_REF,
4306                     'PROP_NAME', 'InstanceCount()',
4307                     'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
4308                     'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path)),
4309                 p_warning_location => 'apply_system_property');
4310 
4311            END IF;
4312 
4313            emit_invokevirtual ('IPortExprDef.card()');
4314 
4315         ELSIF ( p_template_id NOT IN ( h_templates ('value')
4316                                      , h_templates ('integervalue')
4317                                      , h_templates ('decimalvalue')
4318                                      )) THEN
4319 
4320            --#<should never happen>
4321            -- 'Unknown property template "^TEMPLATE" found. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
4322            report_and_raise_rule_sys_warn(
4323                 p_text => GET_NOT_TRANSLATED_TEXT(
4324                     CZ_FCE_SW_UNKNOWN_TEMPLATE,
4325                     'TEMPLATE', p_template_id ),
4326                 p_warning_location => 'apply_system_property' );
4327 
4328         END IF;
4329 
4330         IF ( l_is_bom AND t_psn_psnodetype ( p_index ) <> h_psntypes ('bommodel') AND p_template_id <> h_templates ('state')) THEN
4331 
4332            --For 'state' this call has already been done.
4333 
4334            emit_invokevirtual ('ISingletonExprDef.getVarRef(IExprDef)');
4335 
4336         END IF;
4337      END apply_system_property;
4338      ----------------------------------------------------------------------------------
4339      -- Scope: compile_constraints
4340      PROCEDURE generate_system_property ( p_template_id IN NUMBER
4341                                         , p_node_id IN NUMBER
4342                                         , p_expl_id IN NUMBER
4343                                         , p_input_context IN expression_context
4344                                         , x_output_context IN OUT NOCOPY expression_context
4345                                         ) IS
4346 
4347         l_return            PLS_INTEGER;
4348         l_index             PLS_INTEGER;
4349 
4350         l_is_bom            BOOLEAN;
4351         l_is_bomreference   BOOLEAN;
4352 
4353      BEGIN
4354 
4355         l_index := h_psnid_backindex ( TO_CHAR ( p_node_id ));
4356         l_is_bom := is_bom_node ( l_index );
4357         l_is_bomreference := is_bom_port ( l_index );
4358 
4359         IF ( l_is_bomreference AND ( h_quantities.EXISTS ( TO_CHAR ( p_template_id )) OR p_template_id = h_templates ('selectioncount'))) THEN
4360 
4361            l_return := generate_path ( t_psn_referenceid ( l_index ), p_expl_id, p_input_context, x_output_context );
4362 
4363         ELSE
4364 
4365            l_return := generate_path ( t_psn_psnodeid ( l_index ), p_expl_id, p_input_context, x_output_context );
4366 
4367         END IF;
4368 
4369         IF ( l_return = const_quantifier_created AND ( NOT ( l_is_bom OR l_is_bomreference ))) THEN
4370 
4371            --If this is not a bom node and it is necessary to apply getExprFromInstance, we need to
4372            --do it before applying the property.
4373 
4374            emit_invokevirtual('IInstanceQuantifier.getExprFromInstance(IExprDef)');
4375 
4376         END IF;
4377 
4378         apply_system_property ( p_template_id, l_index, p_input_context );
4379 
4380         IF ( p_input_context.context_type = const_context_contributor AND l_is_bomreference AND h_quantities.EXISTS ( TO_CHAR ( p_template_id ))) THEN
4381 
4382             l_return := const_resourcesum_required;
4383 
4384         END IF;
4385 
4386         IF ( l_is_bom OR l_is_bomreference ) THEN
4387 
4388            --For bom nodes, the result of applying property is a variable, so, if necessary, we need to call
4389            --getExprFromInstance on this variable.
4390 
4391            IF ( l_return = const_quantifier_created ) THEN emit_invokevirtual('IInstanceQuantifier.getExprFromInstance(IExprDef)'); END IF;
4392 
4393         END IF;
4394 
4395         IF ( l_return = const_resourcesum_required ) THEN
4396 
4397            emit_invokevirtual('IPortExprDef.sum(INumExprDef)');
4398 
4399         END IF;
4400      END generate_system_property;
4401      ----------------------------------------------------------------------------------
4402      -- Scope: compile_constraints
4403      PROCEDURE apply_context ( p_node_id IN NUMBER, p_instance IN PLS_INTEGER, p_input_context IN PLS_INTEGER ) IS
4404 
4405         l_index            PLS_INTEGER;
4406         l_is_bom           BOOLEAN;
4407 
4408      BEGIN
4409 
4410         l_index := h_psnid_backindex ( TO_CHAR ( p_node_id));
4411         l_is_bom := is_bom_node ( l_index );
4412 
4413         IF ( p_input_context = const_context_logical ) THEN
4414 
4415             apply_logical_context ( p_node_id, p_input_context );
4416 
4417         END IF;
4418 
4419      END apply_context;
4420      ----------------------------------------------------------------------------------
4421      --Nodes other than targets and contributors can be stored in local variables using
4422      --the following key:
4423 
4424      --ps_node_id-model_ref_expl_id
4425 
4426      --This procedure can be used to restore such nodes from the local variable. The
4427      --path will be regenerated if necessary. Note that if this node has an instance
4428      --quantifier, associated with it, the key for this quanitifer will be added to
4429      --the global quantifier arrays so that if this node participates in constraint,
4430      --correct ForAll will be generated by addConstraint call.
4431 
4432      --The input context is not passed to generate_path. It is only used to apply to
4433      --the context after path is generated.
4434      -- Scope: compile_constraints
4435      PROCEDURE aload_context_node ( p_key IN VARCHAR2, p_input_context IN PLS_INTEGER ) IS
4436 
4437         l_input_context    expression_context;
4438         l_output_context   expression_context;
4439 
4440         l_return           PLS_INTEGER;
4441         l_index            PLS_INTEGER;
4442         l_count            PLS_INTEGER;
4443         l_node_id          NUMBER;
4444         l_expl_id          NUMBER;
4445 
4446         tl_complete_path   type_number_table;
4447         l_key              VARCHAR2(4000);
4448 
4449      BEGIN
4450 
4451         l_node_id := TO_NUMBER ( SUBSTR ( p_key, 1, INSTR ( p_key, '-' ) - 1));
4452         l_expl_id := TO_NUMBER ( SUBSTR ( p_key, INSTR ( p_key, '-' ) + 1));
4453 
4454         IF ( NOT local_variable_defined ( p_key )) THEN
4455 
4456            l_return := generate_path ( l_node_id, l_expl_id, l_input_context, l_output_context );
4457 
4458         ELSE
4459 
4460            --If the variable is defined, we need to also take care of related quantifiers if any.
4461            --We just add them to the global quantifier arrays, the rest will be done by
4462            --aload_quantifier when necessary.
4463 
4464            aload_local_variable ( p_key );
4465 
4466            tl_complete_path := build_complete_path ( l_node_id, l_expl_id );
4467            l_count := tl_complete_path.COUNT;
4468 
4469            IF ( l_count > 0 ) THEN
4470 
4471               --Find the deepest port, this will be the instance quantifier to use in forAll.
4472 
4473               l_index := 2;
4474 
4475               --#<important>
4476               --Using h_psnid_detailedtype is very essential here and in the next block. If any changes are made
4477               --to the definition of h_psnid_detailedtype array, this code may need to change.
4478 
4479               WHILE ( l_index <= l_count AND h_psnid_detailedtype ( tl_complete_path ( l_index )) NOT IN
4480                        (h_psntypes ('component'), h_psntypes ('reference'), h_psntypes ('connector'))) LOOP
4481 
4482                   l_index := l_index + 1;
4483 
4484               END LOOP;
4485 
4486               l_key := TO_CHAR ( tl_complete_path ( l_count ));
4487 
4488               FOR i IN REVERSE l_index..l_count - 1 LOOP
4489 
4490                  l_key := l_key || '_' || TO_CHAR ( tl_complete_path ( i ));
4491 
4492               END LOOP;
4493 
4494               IF ( l_index <= l_count ) THEN
4495 
4496                  IF ( NOT h_instancequantifiers.EXISTS ( l_key )) THEN
4497 
4498                     t_instancequantifiers ( t_instancequantifiers.COUNT + 1 ) := l_key;
4499                     h_instancequantifiers ( l_key ) := 1;
4500 
4501                  END IF;
4502               END IF;
4503            END IF;
4504         END IF;
4505 
4506         apply_context ( l_node_id, l_return, p_input_context );
4507 
4508      END aload_context_node;
4509      ----------------------------------------------------------------------------------
4510      -- Scope: compile_constraints
4511      PROCEDURE generate_node ( j IN PLS_INTEGER
4512                              , p_input_context IN expression_context
4513                              , x_output_context IN OUT NOCOPY expression_context
4514                              ) IS
4515 
4516         l_return          PLS_INTEGER;
4517         l_node_id         NUMBER;
4518         l_is_bom          BOOLEAN;
4519         l_index           PLS_INTEGER;
4520 
4521      BEGIN
4522 
4523         l_node_id := t_exp_psnodeid ( j );
4524         l_index := h_psnid_backindex ( TO_CHAR ( l_node_id ));
4525 
4526         l_is_bom := is_bom_node ( l_index );
4527 
4528         l_return := generate_path ( t_exp_psnodeid ( j ), t_exp_modelrefexplid ( j ), p_input_context, x_output_context );
4529 
4530         IF ( l_return = const_quantifier_created AND ( NOT l_is_bom )) THEN
4531 
4532            emit_invokevirtual('IInstanceQuantifier.getExprFromInstance(IExprDef)');
4533 
4534         END IF;
4535 
4536         IF ( logical_context ( j, p_input_context.context_type )) THEN
4537 
4538             apply_logical_context ( l_node_id, p_input_context.context_type );
4539 
4540         ELSIF ( numeric_context ( j, p_input_context.context_type )) THEN
4541 
4542             apply_numeric_context ( l_node_id, p_input_context.context_type );
4543 
4544         END IF;
4545 
4546         IF ( l_return = const_quantifier_created AND l_is_bom ) THEN
4547 
4548            emit_invokevirtual('IInstanceQuantifier.getExprFromInstance(IExprDef)');
4549 
4550         END IF;
4551 
4552         IF ( l_return = const_resourcesum_required ) THEN
4553 
4554             emit_invokevirtual('IPortExprDef.sum(INumExprDef)');
4555 
4556         END IF;
4557      END generate_node;
4558      ----------------------------------------------------------------------------------
4559      -- Scope: compile_constraints
4560      PROCEDURE generate_logical_options ( j IN PLS_INTEGER
4561                                         , p_input_context IN expression_context
4562                                         , x_output_context IN OUT NOCOPY expression_context
4563                                         ) IS
4564 
4565         l_parent_id        VARCHAR2(4000);
4566         l_node_id          VARCHAR2(4000);
4567         l_expl_id          NUMBER;
4568 
4569         l_logic_operator   NUMBER;
4570 
4571         l_last_index       PLS_INTEGER;
4572         l_index            PLS_INTEGER;
4573         l_return           PLS_INTEGER;
4574 
4575         t_children         type_iteratornode_table;
4576 
4577      BEGIN
4578 
4579         l_parent_id := TO_CHAR ( t_exp_exprparentid ( j ));
4580 
4581         IF ( l_parent_id IS NULL ) THEN
4582 
4583               --#<should never happen>
4584               report_and_raise_rule_sys_warn(
4585                 p_text => GET_NOT_TRANSLATED_TEXT(
4586                     CZ_FCE_SW_OPTIONS_PARENT_NULL),
4587                 p_warning_location => 'generate_logical_options' );
4588 
4589         END IF;
4590 
4591         l_node_id := TO_CHAR ( t_exp_psnodeid ( j ));
4592         l_expl_id := t_exp_modelrefexplid ( j );
4593         l_index := h_psnid_backindex ( l_node_id );
4594 
4595         --If this is a BOM Reference, switch to the referenced BOM Model.
4596 
4597         IF ( is_bom_port ( l_index )) THEN
4598 
4599            l_node_id := TO_CHAR ( t_psn_referenceid ( l_index ));
4600            l_index := h_psnid_backindex ( l_node_id );
4601 
4602         END IF;
4603 
4604         --<#temporary>
4605         --Options() cannot be called on a node that has no children.
4606 
4607         IF ( node_has_children ( l_node_id )) THEN
4608 
4609           l_last_index := h_psnid_lastchildindex ( l_node_id );
4610 
4611         ELSE
4612 
4613           -- Node ^NODE_NAME has no children.  Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
4614 
4615           report_and_raise_rule_warning (
4616               p_text => CZ_UTILS.GET_TEXT( CZ_FCE_W_NODE_MUST_HAVE_CHILD,
4617                         'NODE_NAME', CZ_FCE_COMPILE_UTILS.GET_NODE_PATH( l_node_id,
4618                           ps_node_id_table_to_string(
4619                                 build_complete_path(l_node_id, l_expl_id))),
4620                         'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name ),
4621                         'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH ( p_component_id, p_model_path)
4622                         ),
4623               p_warning_location => 'generate_logical_options');
4624 
4625         END IF;
4626 
4627         l_return := generate_path ( l_node_id, t_exp_modelrefexplid ( j ), p_input_context, x_output_context );
4628 
4629         IF ( t_psn_detailedtype ( l_index ) = h_psntypes ('optionfeature')) THEN
4630 
4631             l_logic_operator := t_exp_templateid ( h_exprid_backindex ( l_parent_id ));
4632 
4633             IF ( l_return = const_quantifier_created ) THEN emit_invokevirtual('IInstanceQuantifier.getExprFromInstance(IExprDef)'); END IF;
4634 
4635             CASE l_logic_operator
4636 
4637                WHEN h_templates ('anytrue') THEN
4638 
4639                    any_option_selected ();
4640 
4641                WHEN h_templates ('alltrue') THEN
4642 
4643                    all_options_selected ( h_psnid_numberofchildren ( l_node_id ));
4644 
4645                ELSE
4646 
4647                   -- 'Invalid parent operator "^OPERATOR" for property options(). Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
4648                   report_and_raise_rule_sys_warn(
4649                     p_text => GET_NOT_TRANSLATED_TEXT(
4650                         CZ_FCE_SW_OPTIONS_PARENT_INVA,
4651                         'OPERATOR', l_logic_operator),
4652                     p_warning_location => 'generate_logical_options' );
4653 
4654             END CASE;
4655 
4656         ELSE
4657 
4658           --We are generating Options() on a bom node, explode its children.
4659 
4660           t_children := explode_bom_children ( l_node_id, t_exp_modelrefexplid ( j ), l_index + 1, l_last_index, FALSE );
4661 
4662           --Adjust the actual number of children of the parent operator as it may be used for generation.
4663           --We replace the one child with Options() applied by the number of its children.
4664 
4665           h_exprid_numberofchildren ( l_parent_id ) := h_exprid_numberofchildren ( l_parent_id ) + t_children.COUNT - 1;
4666 
4667           --Store the generated parent in a local variable. This object will be used for each child.
4668 
4669           IF ( h_psnid_psnodetype ( l_node_id ) <> h_psntypes ('bommodel')) THEN astore_local_variable ( 'var' ); END IF;
4670 
4671           --If there is an instance quantifier, it is now on top of stack. Also need to store.
4672 
4673           IF ( l_return = const_quantifier_created ) THEN astore_local_variable ( 'iq' ); END IF;
4674 
4675           FOR i IN 1..t_children.COUNT LOOP
4676 
4677              IF ( l_return = const_quantifier_created ) THEN aload_local_variable ( 'iq' ); END IF;
4678 
4679              IF ( h_psnid_psnodetype ( l_node_id ) = h_psntypes ('bommodel')) THEN
4680 
4681                 push_variable ( t_children ( i ).ps_node_id, 'IInstanceQuantifier');
4682 
4683              ELSE
4684 
4685                 aload_local_variable ( 'var' );
4686                 push_variable ( t_children ( i ).ps_node_id, 'ISingletonExprDef');
4687                 emit_invokevirtual ('ISingletonExprDef.getVarRef(IExprDef)');
4688 
4689              END IF;
4690 
4691              apply_bom_logical_context ( t_children ( i ).ps_node_id, l_return );
4692 
4693           END LOOP;
4694         END IF;
4695      END generate_logical_options;
4696      ----------------------------------------------------------------------------------
4697      -- Scope: compile_constraints
4698      PROCEDURE generate_numeric_options ( j IN PLS_INTEGER
4699                                         , p_template_id IN NUMBER
4700                                         , p_optional_only IN BOOLEAN
4701                                         , p_input_context IN expression_context
4702                                         , x_output_context IN OUT NOCOPY expression_context
4703                                         ) IS
4704 
4705         l_template_id      NUMBER := p_template_id;
4706 
4707         l_parent_id        VARCHAR2(4000);
4708         l_node_id          VARCHAR2(4000);
4709         l_expl_id          NUMBER;
4710 
4711         l_last_index       PLS_INTEGER;
4712         l_index            PLS_INTEGER;
4713         l_return           PLS_INTEGER;
4714 
4715         t_children         type_iteratornode_table;
4716 
4717      BEGIN
4718 
4719         l_node_id := TO_CHAR ( t_exp_psnodeid ( j ));
4720         l_expl_id := t_exp_modelrefexplid ( j );
4721         l_index := h_psnid_backindex ( l_node_id );
4722 
4723         --If this is a BOM Reference, switch to the referenced BOM Model.
4724 
4725         IF ( is_bom_port ( l_index )) THEN
4726 
4727             l_node_id := TO_CHAR ( t_psn_referenceid ( l_index ));
4728             l_index := h_psnid_backindex ( l_node_id );
4729 
4730         END IF;
4731 
4732         --<#temporary>
4733         --Options() cannot be called on a node that has no children.
4734 
4735         IF ( node_has_children ( l_node_id )) THEN
4736 
4737           l_last_index := h_psnid_lastchildindex ( l_node_id );
4738 
4739         ELSE
4740 
4741            report_and_raise_rule_warning (
4742                 p_text => CZ_UTILS.GET_TEXT( CZ_FCE_W_NODE_MUST_HAVE_CHILD,
4743                         'NODE_NAME', CZ_FCE_COMPILE_UTILS.GET_NODE_PATH( l_node_id,
4744                           ps_node_id_table_to_string(
4745                                 build_complete_path(l_node_id, l_expl_id) ) ),
4746                         'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name ),
4747                         'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH ( p_component_id, p_model_path)
4748                         ),
4749                 p_warning_location => 'generate_numeric_options');
4750 
4751         END IF;
4752 
4753         IF ( t_psn_detailedtype ( l_index ) = h_psntypes ('optionfeature')) THEN
4754 
4755             l_return := generate_path ( l_node_id, t_exp_modelrefexplid ( j ), p_input_context, x_output_context );
4756 
4757             IF ( l_return = const_quantifier_created ) THEN emit_invokevirtual('IInstanceQuantifier.getExprFromInstance(IExprDef)'); END IF;
4758 
4759             --Options() is applied to an option feature. Need to generate card() for both counted or
4760             --non-counted option feature.
4761 
4762             emit_invokevirtual ('ISetExprDef.card()');
4763             IF ( l_return = const_resourcesum_required ) THEN emit_invokevirtual('IPortExprDef.sum(INumExprDef)'); END IF;
4764 
4765         ELSE
4766 
4767           --We are generating Options() on a bom node in numeric context, default the bom property.
4768 
4769           IF ( l_template_id IS NULL ) THEN l_template_id := h_templates ('quantity'); END IF;
4770           IF ( NOT h_quantities.EXISTS ( l_template_id )) THEN
4771              -- 'In the numeric context invalid property applied to a BOM node. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
4772              report_and_raise_rule_sys_warn(
4773                     p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_BOM_NUM_INVALPROP ),
4774                     p_warning_location => 'generate_numeric_options' );
4775           END IF;
4776 
4777           t_children := explode_bom_children ( l_node_id, t_exp_modelrefexplid ( j ), l_index + 1, l_last_index, p_optional_only );
4778           l_parent_id := TO_CHAR ( t_exp_exprparentid ( j ));
4779 
4780           --Adjust the actual number of children of the parent operator as it may be used for generation.
4781           --We replace the one child with Options() applied by the number of its children.
4782 
4783           h_exprid_numberofchildren ( l_parent_id ) := h_exprid_numberofchildren ( l_parent_id ) + t_children.COUNT - 1;
4784 
4785           IF ( t_children.COUNT > 2 ) THEN
4786 
4787              --If there are more than two chilren, we will be summing them up later, so we need
4788              --a model def for that. It will be used by sum_numeric procedure.
4789 
4790              aload_model_def ( p_component_id );
4791 
4792           END IF;
4793 
4794           l_return := generate_path ( l_node_id, t_exp_modelrefexplid ( j ), p_input_context, x_output_context );
4795 
4796           --Store the generated parent in a local variable. This object will be used for each child.
4797 
4798           IF ( h_psnid_psnodetype ( l_node_id ) <> h_psntypes ('bommodel')) THEN astore_local_variable ( 'var' ); END IF;
4799 
4800           --Next on stack is either an instance quantifier, or a port that will require sum in case of
4801           --contributor. Also need to store.
4802 
4803           IF ( l_return <> const_no_instances ) THEN astore_local_variable ( 'iq' ); END IF;
4804 
4805           FOR i IN 1..t_children.COUNT LOOP
4806 
4807              IF ( l_return <> const_no_instances ) THEN aload_local_variable ( 'iq' ); END IF;
4808 
4809              IF ( h_psnid_psnodetype ( l_node_id ) = h_psntypes ('bommodel')) THEN
4810 
4811                IF ( l_return = const_quantifier_created ) THEN
4812 
4813                    push_variable ( t_children ( i ).ps_node_id, 'IInstanceQuantifier');
4814 
4815                ELSE
4816 
4817                    push_variable ( t_children ( i ).ps_node_id, 'IPortExprDef');
4818 
4819                END IF;
4820 
4821              ELSE
4822 
4823                 aload_local_variable ( 'var' );
4824                 push_variable ( t_children ( i ).ps_node_id, 'ISingletonExprDef');
4825                 emit_invokevirtual ('ISingletonExprDef.getVarRef(IExprDef)');
4826 
4827              END IF;
4828 
4829              IF ( t_psn_psnodetype ( t_children ( i ).expr_index ) IN ( h_psntypes ('bomoptionclass'), h_psntypes ('bomstandard'))) THEN
4830 
4831                  apply_bom_property ( h_quantities ( l_template_id ));
4832                  IF ( l_return = const_resourcesum_required ) THEN emit_invokevirtual('IPortExprDef.sum(INumExprDef)'); END IF;
4833 
4834              ELSE
4835 
4836                  --This is a bom port.
4837 
4838                  emit_dup ();
4839                  emit_invokevirtual ('IPortExprDef.getType()');
4840                  emit_invokevirtual ( h_quantities ( l_template_id ));
4841                  emit_invokevirtual('IPortExprDef.sum(INumExprDef)');
4842 
4843              END IF;
4844 
4845              IF ( l_return = const_quantifier_created ) THEN emit_invokevirtual('IInstanceQuantifier.getExprFromInstance(IExprDef)'); END IF;
4846 
4847           END LOOP;
4848 
4849           --We need to sum up all the generated numeric expressions into a contributor term.
4850 
4851           sum_numeric ( t_children.COUNT );
4852 
4853         END IF;
4854      END generate_numeric_options;
4855      ----------------------------------------------------------------------------------
4856      -- Scope: compile_constraints
4857      PROCEDURE generate_options ( j IN PLS_INTEGER
4858                                 , p_input_context IN expression_context
4859                                 , x_output_context IN OUT NOCOPY expression_context
4860                                 ) IS
4861      BEGIN
4862 
4863         IF ( numeric_context ( j, p_input_context.context_type )) THEN
4864 
4865            generate_numeric_options ( j, NULL, FALSE, p_input_context, x_output_context );
4866 
4867         ELSIF ( logical_context ( j, p_input_context.context_type )) THEN
4868 
4869            generate_logical_options ( j, p_input_context, x_output_context );
4870 
4871         ELSE
4872 
4873            -- 'Unknown context occurred for options(). Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
4874            report_and_raise_rule_sys_warn(
4875                     p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_UNKNOWN_CONTEXT ),
4876                     p_warning_location => 'generate_options' );
4877 
4878         END IF;
4879      END generate_options;
4880      ----------------------------------------------------------------------------------
4881      --This procedure should be called when the generated expression is on top of stack.
4882      --Does not change the state of stack.
4883      -- Scope: compile_constraints
4884 
4885      PROCEDURE set_reason_id IS
4886 
4887         l_id     NUMBER;
4888         l_text   cz_localized_texts.localized_str%TYPE;
4889 
4890      BEGIN
4891 
4892         --reason_id for constraints, for which we call this procedure, cannot be null, so
4893         --it should be possible to remove this condition.
4894 
4895         IF ( this_reason_id IS NOT NULL ) THEN
4896 
4897            --Bug #6899574. Need to get the persistent id of localized text record.
4898 
4899            SELECT persistent_intl_text_id, localized_str INTO l_id, l_text FROM cz_localized_texts
4900             WHERE deleted_flag = '0' AND language = USERENV ('LANG') AND intl_text_id = this_reason_id;
4901 
4902            comment ( 'Set rule violation message: "' || l_text || '"' );
4903 
4904            emit_dup ();
4905            push_long_constant ( l_id );
4906            emit_invokevirtual('IExprDef.setId(long)');
4907 
4908            --Remove the null object from stack after a void method.
4909 
4910            emit_pop ( 1 );
4911 
4912         END IF;
4913 
4914      EXCEPTION
4915        WHEN NO_DATA_FOUND THEN
4916 
4917           report_and_raise_rule_sys_warn ( p_text => CZ_FCE_SW_NO_INTL_TEXT, p_warning_location => 'set_reason_id' );
4918 
4919      END set_reason_id;
4920      ----------------------------------------------------------------------------------
4921      --This procedure should be called when the generated expression is on top of stack.
4922      --Does not change the state of stack.
4923     -- Scope: compile_constraints
4924      PROCEDURE add_constraint IS
4925 
4926         l_method   VARCHAR2(4000);
4927 
4928      BEGIN
4929 
4930         emit_effectivity ( 'ILogicExprDef', this_effective_from, this_effective_until, this_effective_usages );
4931 
4932         l_method := 'IModelDef.add' || CASE NVL ( this_rule_class, h_ruleclasses ('constraint'))
4933                WHEN h_ruleclasses ('constraint') THEN 'Constraint'
4934                WHEN h_ruleclasses ('default') THEN 'DefaultDecision'
4935                WHEN h_ruleclasses ('search') THEN 'SearchDecision' END;
4936 
4937         --Finish generation of the constraint and add it to the model def.
4938 
4939         IF ( t_instancequantifiers.COUNT > 0 ) THEN
4940 
4941           --There were instance quantifiers generated, so we need a ForAll and an extra root model
4942           --def to call ForAll on. But first we need to store the generated expression, which then
4943           --will be passed as the last argument to ForAll.
4944 
4945           --Store the generated expression in a local variable. May be, a new instruction would be
4946           --better, something about storing in a register. We can use aload_local_variable here as
4947           --there is no way this local variable will be replaced with something else while we load
4948           --quantifiers.
4949 
4950           --Note, that if forAll method had ILogicExprDef as the first parameter we'd just need to
4951           --swap it with the model def.
4952 
4953           astore_local_variable ( 'exp' );
4954           aload_model_def ( p_component_id );
4955 
4956           FOR i IN 1..t_instancequantifiers.COUNT LOOP
4957 
4958              aload_quantifier ( t_instancequantifiers ( i ));
4959 
4960           END LOOP;
4961 
4962           CASE t_instancequantifiers.COUNT
4963 
4964              WHEN 1 THEN
4965 
4966                 aload_local_variable ( 'exp' );
4967                 emit_invokevirtual('IModelDef.forAll(IInstanceQuantifier, ILogicExprDef)');
4968 
4969              WHEN 2 THEN
4970 
4971                 aload_local_variable ( 'exp' );
4972                 emit_invokevirtual('IModelDef.forAll(IInstanceQuantifier, IInstanceQuantifier, ILogicExprDef)');
4973 
4974              ELSE
4975 
4976                 create_array ( t_instancequantifiers.COUNT, h_javatypes ('IInstanceQuantifier'));
4977                 populate_array ( t_instancequantifiers.COUNT );
4978                 aload_local_variable ( 'exp' );
4979                 emit_invokevirtual('IModelDef.forAll(IInstanceQuantifier[], ILogicExprDef)');
4980 
4981           END CASE;
4982 
4983           emit_invokevirtual( l_method || '(IForAllDef)');
4984 
4985         ELSE
4986 
4987           emit_invokevirtual( l_method || '(ILogicExprDef)');
4988 
4989         END IF;
4990 
4991         --Remove the null object from stack after a void method.
4992 
4993         emit_pop ( 1 );
4994 
4995      END add_constraint;
4996      ----------------------------------------------------------------------------------
4997          -- Scope: compile_constraints
4998      FUNCTION push_numeric_literal ( p_value IN NUMBER ) RETURN PLS_INTEGER IS
4999      BEGIN
5000 
5001         IF ( ROUND ( p_value ) = p_value ) THEN
5002 
5003            push_integer_constant ( p_value );
5004            RETURN h_datatypes ('integer');
5005 
5006         ELSE
5007 
5008            push_decimal_constant ( p_value );
5009            RETURN h_datatypes ('decimal');
5010 
5011         END IF;
5012      END push_numeric_literal;
5013      ----------------------------------------------------------------------------------
5014          -- Scope: compile_constraints
5015      FUNCTION get_literal_value ( j IN PLS_INTEGER ) RETURN VARCHAR2 IS
5016 
5017         l_val   NUMBER;
5018 
5019      BEGIN
5020 
5021        IF ( t_exp_datatype ( j ) IN ( h_datatypes ('integer'), h_datatypes ('decimal'))) THEN
5022 
5023           RETURN TO_CHAR ( t_exp_datanumvalue ( j ));
5024 
5025        ELSIF ( t_exp_datatype ( j ) IN ( h_datatypes ('boolean'), h_datatypes ('text'))) THEN
5026 
5027           RETURN t_exp_datavalue ( j );
5028 
5029        ELSIF ( t_exp_datatype ( j ) IS NULL ) THEN
5030 
5031           --#<temporary>
5032           --Developer does not populate data_type for constants in simple comparison rules.
5033           --Such constants can only be numeric, but the value is in data_value column.
5034           --It would be more consistent to have data_type column always populated for
5035           --literals and throw an inconsistency exception here.
5036 
5037           l_val := TO_NUMBER ( NVL ( t_exp_datanumvalue ( j ), t_exp_datavalue ( j )));
5038 
5039           --Need to populate data_type properly, because it is used to select the best signature.
5040 
5041           t_exp_datatype ( j ) := CASE ROUND ( l_val ) WHEN l_val THEN h_datatypes ('integer') ELSE h_datatypes ('decimal') END;
5042           RETURN l_val;
5043 
5044        ELSE
5045 
5046           --#<should never happen>
5047           -- 'Invalid literal data type "^TYPE" found for the expression with the id ^EXPR_ID. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
5048           report_and_raise_rule_sys_warn(
5049                     p_text => GET_NOT_TRANSLATED_TEXT(
5050                         CZ_FCE_SW_INVALID_LIT_DTYPE,
5051                         'TYPE', t_exp_datatype ( j ),
5052                         'EXPR_ID', t_exp_exprnodeid ( j )),
5053                     p_warning_location => 'get_literal_value' );
5054           RETURN NULL;
5055 
5056        END IF;
5057      END get_literal_value;
5058      ----------------------------------------------------------------------------------
5059          -- Scope: compile_constraints
5060      PROCEDURE push_constant_expr ( p_value IN VARCHAR2, p_data_type IN NUMBER ) IS
5061      BEGIN
5062 
5063        IF ( p_data_type NOT IN ( h_datatypes ('integer'), h_datatypes ('decimal'), h_datatypes ('boolean'))) THEN
5064 
5065           --#<should never happen>
5066           -- 'Invalid constant data type "^TYPE" found. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
5067           report_and_raise_rule_sys_warn(
5068                     p_text => GET_NOT_TRANSLATED_TEXT(
5069                         CZ_FCE_SW_INVAL_CONST_DTYPE,
5070                         'TYPE', p_data_type),
5071                     p_warning_location => 'push_constant_expr' );
5072 
5073        END IF;
5074 
5075        IF ( p_value IS NULL ) THEN
5076            -- 'Null constant value occurred. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
5077            report_and_raise_rule_sys_warn(
5078                     p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_NULL_CONSTANT_VALUE),
5079                     p_warning_location => 'push_constant_expr' );
5080 
5081        END IF;
5082 
5083        aload_model_def ( p_component_id );
5084 
5085        CASE p_data_type
5086 
5087          WHEN h_datatypes('integer') THEN
5088 
5089             push_integer_constant ( TO_NUMBER ( p_value ));
5090             emit_invokevirtual('IModelDef.literal(int)');
5091 
5092          WHEN h_datatypes('decimal') THEN
5093 
5094             push_decimal_constant ( TO_NUMBER ( p_value ));
5095             emit_invokevirtual('IModelDef.literal(double)');
5096 
5097          WHEN h_datatypes('boolean') THEN
5098 
5099             emit_boolean ( p_value );
5100             emit_invokevirtual('IModelDef.literal(boolean)');
5101 
5102        END CASE;
5103 
5104      EXCEPTION
5105         WHEN INVALID_NUMBER THEN
5106 
5107              --#<should never happen>
5108              -- 'Invalid number "^VALUE" found. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
5109              report_and_raise_rule_sys_warn(
5110                     p_text => GET_NOT_TRANSLATED_TEXT(
5111                         CZ_FCE_SW_INVALID_NUMBER,
5112                         'VALUE', p_value ),
5113                   p_warning_location => 'push_constant_expr:' || DBMS_UTILITY.FORMAT_ERROR_STACK ||
5114                   '\nBack Trace:' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
5115 
5116      END push_constant_expr;
5117      ----------------------------------------------------------------------------------
5118      -- Scope: compile_constraints
5119      PROCEDURE push_constant ( p_value IN VARCHAR2, p_data_type IN NUMBER ) IS
5120      BEGIN
5121 
5122        IF ( p_value IS NULL ) THEN
5123            -- 'Null constant value occurred. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
5124            report_and_raise_rule_sys_warn(
5125                     p_text => GET_NOT_TRANSLATED_TEXT(
5126                         CZ_FCE_SW_NULL_CONSTANT_VALUE),
5127                     p_warning_location => 'push_constant_expr' );
5128 
5129 
5130        END IF;
5131 
5132        CASE p_data_type
5133 
5134          WHEN h_datatypes ('integer') THEN
5135 
5136             push_integer_constant ( TO_NUMBER ( p_value ));
5137 
5138          WHEN h_datatypes ('decimal') THEN
5139 
5140             push_decimal_constant ( TO_NUMBER ( p_value ));
5141 
5142          WHEN h_datatypes ('boolean') THEN
5143 
5144             emit_boolean ( p_value );
5145 
5146          WHEN h_datatypes ('text') THEN
5147 
5148             push_string_constant ( p_value );
5149 
5150          ELSE
5151 
5152              --#<should never happen>
5153              -- 'Invalid constant data type "^TYPE" found. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
5154              report_and_raise_rule_sys_warn(
5155                 p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_INVAL_CONST_DTYPE ),
5156                 p_warning_location => 'push_constant' );
5157 
5158        END CASE;
5159 
5160      EXCEPTION
5161         WHEN INVALID_NUMBER THEN
5162 
5163              --#<should never happen>
5164              -- 'Invalid number "^VALUE" found. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
5165              report_and_raise_rule_sys_warn(
5166                     p_text => GET_NOT_TRANSLATED_TEXT(
5167                         CZ_FCE_SW_INVALID_NUMBER,
5168                         'VALUE', p_value ),
5169                   p_warning_location => 'push_constant:' || DBMS_UTILITY.FORMAT_ERROR_STACK ||
5170                   '\nBack Trace:' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
5171 
5172      END push_constant;
5173      ----------------------------------------------------------------------------------
5174      -- Scope: compile_constraints
5175      PROCEDURE generate_constant ( j IN PLS_INTEGER ) IS
5176 
5177         l_template_id   NUMBER := t_exp_templateid ( j );
5178 
5179      BEGIN
5180 
5181         IF ( l_template_id NOT IN ( h_mathconstants ('e'), h_mathconstants ('pi'))) THEN
5182            -- 'Mathematical operator is not implemented for template_id "^TEMPL_ID". Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
5183            report_and_raise_rule_sys_warn(
5184               p_text => GET_NOT_TRANSLATED_TEXT(
5185                     CZ_FCE_SW__NO_MATH_CONST,
5186                     'TEMPL_ID', l_template_id ),
5187               p_warning_location => 'generate_constant' );
5188         END IF;
5189 
5190         emit_constant ( l_template_id );
5191 
5192      END generate_constant;
5193      ----------------------------------------------------------------------------------
5194      -- Scope: compile_constraints
5195      PROCEDURE generate_literal ( j                IN PLS_INTEGER
5196                                 , p_value          IN VARCHAR2
5197                                 , p_data_type      IN NUMBER
5198                                 , p_input_context  IN expression_context
5199                                 , x_output_context IN OUT NOCOPY expression_context ) IS
5200 
5201         l_expr_id       VARCHAR2(4000);
5202         l_index         PLS_INTEGER;
5203         l_count         PLS_INTEGER;
5204 
5205         l_template_id   NUMBER;
5206 
5207      BEGIN
5208 
5209        IF ( p_input_context.context_type = const_context_selection ) THEN
5210 
5211           --This literal partitipates in an expression involving Selection() with a text
5212           --property. We just need to populate data structures that will be used in the
5213           --Selection() generation.
5214 
5215          l_count := s_.COUNT + 1;
5216 
5217          s_( l_count ) := 1;
5218          o_( l_count )( 1 ) := NULL; --this value is not used.
5219          t_( l_count )( 1 )( 1 ) := p_value;
5220 
5221          RETURN;
5222 
5223        END IF;
5224 
5225        IF ( t_exp_exprparentid ( j ) IS NULL ) THEN
5226 
5227           push_constant_expr ( p_value, p_data_type );
5228           RETURN;
5229 
5230        END IF;
5231 
5232        l_expr_id := TO_CHAR ( t_exp_exprparentid ( j ));
5233        l_index := h_exprid_backindex ( l_expr_id );
5234 
5235        l_template_id := t_exp_templateid ( l_index );
5236 
5237        IF ( p_data_type IN ( h_datatypes ('integer'), h_datatypes ('decimal'))) THEN
5238 
5239          IF ( TO_NUMBER ( p_value ) = 1 AND l_template_id IN ( h_templates ('multiply'), h_templates ('div'))) THEN
5240 
5241              --#<optimization>
5242              --The literal is an operand to mutliplication or division, and its value is 1.
5243 
5244              x_output_context.context_type := const_context_literal;
5245              RETURN;
5246 
5247          END IF;
5248        END IF;
5249 
5250        --#<optimization>
5251        --We need to convert the literal to expression if
5252        --  it is the first operand of an operator;
5253        --  it is the only operand;
5254        --  it is any operand of 'array' operators.
5255        --These are not exact conditions and can be enhanced.
5256 
5257        IF ( t_exp_seqnbr ( j ) = 1 OR
5258             h_exprid_numberofchildren ( l_expr_id ) = 1 OR
5259             h_operators_3.EXISTS ( l_template_id )
5260           ) THEN
5261 
5262            push_constant_expr ( p_value, p_data_type );
5263 
5264        ELSE
5265 
5266            push_constant ( p_value, p_data_type );
5267            x_output_context.context_type := const_context_constant;
5268 
5269        END IF;
5270      END generate_literal;
5271      ----------------------------------------------------------------------------------
5272      -- Scope: compile_constraints
5273      PROCEDURE invoke_operator2 ( p_template_id IN PLS_INTEGER, p_rhs_index IN PLS_INTEGER, p_input_context IN expression_context ) IS
5274      BEGIN
5275 
5276         IF ( p_input_context.context_type = const_context_constant OR t_exp_exprtype ( p_rhs_index ) = h_exprtypes ('literal')) THEN
5277 
5278            --The RHS operand is a literal or has been evaluated to a literal.
5279            --Select the best signature for the method to call.
5280 
5281            IF ( t_exp_datatype ( p_rhs_index ) = h_datatypes ('integer')) THEN
5282 
5283               emit_invokevirtual ( h_operators_2_int ( p_template_id ));
5284 
5285            ELSIF ( t_exp_datatype ( p_rhs_index ) = h_datatypes ('decimal')) THEN
5286 
5287               emit_invokevirtual ( h_operators_2_double ( p_template_id ));
5288 
5289            ELSIF ( t_exp_datatype ( p_rhs_index ) = h_datatypes ('boolean')) THEN
5290 
5291               emit_invokevirtual ( h_operators_2_boolean ( p_template_id ));
5292 
5293            ELSE
5294 
5295               emit_invokevirtual ( h_operators_2 ( p_template_id ));
5296 
5297            END IF;
5298 
5299         ELSE
5300 
5301            emit_invokevirtual ( h_operators_2 ( p_template_id ));
5302 
5303         END IF;
5304      END invoke_operator2;
5305      ----------------------------------------------------------------------------------
5306      -- Scope: compile_constraints
5307      PROCEDURE invoke_operator3 ( p_template_id IN PLS_INTEGER, p_count IN PLS_INTEGER, p_type IN VARCHAR2 ) IS
5308      BEGIN
5309 
5310         --Parameters are on stack, create the array.
5311 
5312         create_array ( p_count, h_javatypes ( p_type ));
5313         populate_array ( p_count );
5314 
5315         --To call the method, we need a model def. We have to push it now and swap with
5316         --the array of parameters. We could not push the model def before generation of
5317         --parameters, for example: AnyTrue(F.Options()) - only when we generate Options
5318         --we will have the correct number of children of AnyTrue.
5319 
5320         aload_model_def ( p_component_id );
5321         emit_swap ();
5322         emit_invokevirtual ( h_operators_3 ( p_template_id ));
5323 
5324      END invoke_operator3;
5325      ----------------------------------------------------------------------------------
5326      -- Scope: compile_constraints
5327      PROCEDURE invoke_anyalltrue ( p_template_id IN PLS_INTEGER, p_count IN PLS_INTEGER, p_parent_id IN NUMBER DEFAULT 0 ) IS
5328      BEGIN
5329 
5330         --#<optimization>
5331         --If there is only one actual operand, we don't need to do anything.
5332 
5333         --Bug #6979696. Default and Search decision can have this operator on the root
5334         --level, in which case we need to apply it because we need to call addDecision
5335         --on the result. In many cases when we call this procedure we know it is not a
5336         --decision, so we don't have to specify the p_parent_id.
5337 
5338         IF ( p_count < 2 AND p_parent_id IS NOT NULL ) THEN RETURN; END IF;
5339 
5340         IF ( p_count = 2 ) THEN
5341 
5342            --If there are two parameters, use Or/And instead.
5343 
5344            emit_invokevirtual ( h_operators_3_opt ( p_template_id ));
5345 
5346         ELSE
5347 
5348            invoke_operator3 ( p_template_id, p_count, 'ILogicExprDef' );
5349 
5350         END IF;
5351      END invoke_anyalltrue;
5352      ----------------------------------------------------------------------------------
5353      -- Scope: compile_constraints
5354      FUNCTION get_property_id ( j IN PLS_INTEGER ) RETURN NUMBER IS
5355 
5356         l_type   PLS_INTEGER;
5357 
5358      BEGIN
5359 
5360         IF ( t_exp_exprtype ( j ) IN ( h_exprtypes ('property'), h_exprtypes ('literal'))) THEN
5361 
5362            h_propertyid_type ( TO_CHAR ( t_exp_propertyid ( j ))) := h_exprtypes ('property');
5363            RETURN t_exp_propertyid ( j );
5364 
5365         ELSIF ( t_exp_exprtype ( j ) = h_exprtypes ('systemproperty')) THEN
5366 
5367            h_propertyid_type ( TO_CHAR ( t_exp_templateid ( j ))) := h_exprtypes ('systemproperty');
5368            RETURN t_exp_templateid ( j );
5369 
5370         ELSIF ( t_exp_exprtype ( j ) = h_exprtypes ('argument')) THEN
5371 
5372            --In case of statement ForAll rule, iterator can participate in the where clause without
5373            --any property applied. We emulate this as non-existant system property with property_id
5374            --and data_type equal to the data type of the context.
5375 
5376            l_type := get_context_type ( j );
5377 
5378            h_propertyid_type ( TO_CHAR ( l_type )) := h_exprtypes ('systemproperty');
5379            RETURN l_type;
5380 
5381         ELSE
5382            -- 'No property id found for the expression id "^EXPR_ID". Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
5383            report_and_raise_rule_sys_warn(
5384                 p_text => GET_NOT_TRANSLATED_TEXT(
5385                         CZ_FCE_SW_NO_PROP_ID_EXPR_ID,
5386                         'EXPR_ID', TO_CHAR ( t_exp_exprnodeid ( j )) ),
5387                 p_warning_location => 'get_property_id');
5388            RETURN NULL;
5389 
5390         END IF;
5391      END get_property_id;
5392      ----------------------------------------------------------------------------------
5393      -- Scope: compile_constraints
5394      FUNCTION get_property_type ( p_property_id IN NUMBER ) RETURN PLS_INTEGER IS
5395 
5396         l_property_id   VARCHAR2(4000) := TO_CHAR ( p_property_id );
5397 
5398      BEGIN
5399 
5400         IF ( NOT h_propertyid_type.EXISTS ( l_property_id )) THEN
5401            -- 'No property type found for the property id "^PROP_ID". Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
5402            report_and_raise_rule_sys_warn(
5403                 p_text => GET_NOT_TRANSLATED_TEXT(
5404                         CZ_FCE_SW_NO_TYPE_FOR_PROP_ID,
5405                         'PROP_ID', l_property_id ),
5406                 p_warning_location => 'get_property_type');
5407 
5408         END IF;
5409 
5410         RETURN h_propertyid_type ( l_property_id );
5411      END get_property_type;
5412      ----------------------------------------------------------------------------------
5413      -- Scope: compile_constraints
5414      PROCEDURE get_static_info ( p_property_id  IN NUMBER
5415                                , x_data_type    IN OUT NOCOPY NUMBER
5416                                ) IS
5417 
5418         l_property_id   VARCHAR2(4000);
5419 
5420      BEGIN
5421 
5422         l_property_id := TO_CHAR ( p_property_id );
5423 
5424         IF ( h_propertyid_datatype.EXISTS ( l_property_id )) THEN
5425 
5426             x_data_type := h_propertyid_datatype ( l_property_id );
5427 
5428         ELSE
5429 
5430            IF ( p_property_id = h_templates ('name')) THEN
5431 
5432               x_data_type := h_datatypes('text');
5433 
5434            ELSIF ( p_property_id IN ( h_templates ('minvalue')
5435                                     , h_templates ('maxvalue')
5436                                     , h_templates ('minquantity')
5437                                     , h_templates ('maxquantity')
5438                                     , h_templates ('minselected')
5439                                     , h_templates ('maxselected')
5440                                     )
5441                  ) THEN
5442 
5443               x_data_type := h_datatypes ('decimal');
5444 
5445            ELSIF ( p_property_id IN ( h_datatypes ('decimal')
5446                                     , h_datatypes ('boolean')
5447                                     , h_datatypes ('text')
5448                                     )
5449                  ) THEN
5450 
5451               --Case of iterator without any properties in the where clause of a statement ForAll.
5452 
5453               x_data_type := p_property_id;
5454 
5455            ELSIF ( p_property_id = h_templates ('description')) THEN
5456               -- System Property ^PROP_NAME is invalid in WHERE clause of a COMPATIBLE or FORALL operator because it is translatable. Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
5457               report_and_raise_rule_warning(
5458                 CZ_UTILS.GET_TEXT(CZ_FCE_W_DESCRIPTION_IN_WHERE,
5459                   'PROP_NAME','description',
5460                   'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
5461                   'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path)),
5462                 'get_static_info'
5463                );
5464 
5465            ELSE
5466 
5467               -- System Property ^PROPERTY_NAME is invalid in WHERE clause of
5468               -- COMPATIBLE or FORALL operator because its value is not static at runtime.
5469               -- Rule "^RULE_NAME" in the Model "^MODEL_NAME" ignored.'
5470 
5471               report_and_raise_rule_warning(
5472                 CZ_UTILS.GET_TEXT(CZ_FCE_W_PROPERTY_NOT_STATIC,
5473                   'PROPERTY_NAME',CZ_FCE_COMPILE_UTILS.GET_PROPERTY_PATH(p_property_id),
5474                   'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
5475                   'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path)),
5476                 'get_static_info'
5477                );
5478 
5479            END IF;
5480 
5481            h_propertyid_datatype ( l_property_id ) := x_data_type;
5482 
5483         END IF;
5484      END get_static_info;
5485      ----------------------------------------------------------------------------------
5486      -- Scope: compile_constraints
5487      FUNCTION get_static_value ( p_property_id  IN NUMBER
5488                                , p_node_id      IN NUMBER
5489                                )
5490      RETURN VARCHAR2 IS
5491 
5492         l_key           VARCHAR2(4000);
5493         l_node_id       VARCHAR2(4000);
5494         l_property_id   VARCHAR2(4000);
5495 
5496         l_value         VARCHAR2(4000);
5497         l_index         PLS_INTEGER;
5498 
5499      BEGIN
5500 
5501        l_node_id := TO_CHAR ( p_node_id );
5502        l_property_id := TO_CHAR ( p_property_id );
5503 
5504        l_key := l_node_id || '-' || l_property_id;
5505 
5506        IF ( h_psnid_propertyid_value.EXISTS ( l_key )) THEN
5507 
5508            RETURN h_psnid_propertyid_value ( l_key );
5509 
5510        END IF;
5511 
5512        l_index := h_psnid_backindex ( l_node_id );
5513 
5514        IF ( p_property_id = h_templates ('name')) THEN
5515 
5516            l_value := t_psn_name ( l_index );
5517 
5518        ELSIF ( p_property_id IN ( h_templates ('minvalue')
5519                                 , h_templates ('minquantity')
5520                                 , h_templates ('minselected')
5521                                 )
5522                ) THEN
5523 
5524            l_value := t_psn_minimum ( l_index );
5525 
5526        ELSIF ( p_property_id IN ( h_templates ('maxvalue')
5527                                 , h_templates ('maxquantity')
5528                                 , h_templates ('maxselected')
5529                                 )
5530               ) THEN
5531 
5532            l_value := t_psn_maximum ( l_index );
5533 
5534        ELSE
5535           -- 'Property with the template id "^PROP_ID" is not static. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
5536           report_and_raise_rule_sys_warn(
5537                 p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_NOT_STATIC_PROPERTY,
5538                         'PROP_ID', l_property_id ),
5539                 p_warning_location => 'get_static_value');
5540        END IF;
5541 
5542        h_psnid_propertyid_value ( l_key ) := l_value;
5543        RETURN l_value;
5544 
5545      END get_static_value;
5546      ----------------------------------------------------------------------------------
5547      PROCEDURE get_user_info ( p_property_id  IN NUMBER
5548                              , x_data_type    IN OUT NOCOPY NUMBER
5549                              , x_def_value    IN OUT NOCOPY VARCHAR2
5550                              ) IS
5551 
5552         l_property_id   VARCHAR2(4000);
5553 
5554      BEGIN
5555 
5556         l_property_id := TO_CHAR ( p_property_id );
5557 
5558         IF ( h_propertyid_datatype.EXISTS ( l_property_id )) THEN
5559 
5560             x_data_type := h_propertyid_datatype ( l_property_id );
5561             x_def_value := h_propertyid_defvalue ( l_property_id );
5562 
5563         ELSE
5564 
5565             SELECT NVL( TO_CHAR ( def_num_value ), def_value ), data_type INTO x_def_value, x_data_type
5566               FROM cz_properties
5567              WHERE property_id = p_property_id
5568                AND deleted_flag = '0';
5569 
5570             h_propertyid_datatype ( l_property_id ) := x_data_type;
5571             h_propertyid_defvalue ( l_property_id ) := x_def_value;
5572 
5573         END IF;
5574      END get_user_info;
5575      ----------------------------------------------------------------------------------
5576      -- Scope: compile_constraints
5577      FUNCTION get_user_value ( p_property_id  IN NUMBER
5578                              , p_node_id      IN NUMBER
5579                              , p_expl_id      IN NUMBER
5580                              , p_item_id      IN NUMBER
5581                              )
5582      RETURN VARCHAR2 IS
5583 
5584         l_def_value     VARCHAR2(4000);
5585         l_data_type     NUMBER;
5586         l_key           VARCHAR2(4000);
5587         l_tab           type_varchar4000_table;
5588 
5589         l_node_id       VARCHAR2(4000);
5590         l_property_id   VARCHAR2(4000);
5591 
5592      BEGIN
5593 
5594        l_node_id := TO_CHAR ( p_node_id );
5595        l_property_id := TO_CHAR ( p_property_id );
5596 
5597        --#<temporary>
5598        --This key works well enough for properties, attached to structure nodes directly.
5599        --However, for properties attached through items it can result in excessive
5600        --quering as different ps nodes can have the same item id and hence the same
5601        --property value.
5602 
5603        l_key := l_node_id || '-'  || l_property_id;
5604 
5605        IF ( h_psnid_propertyid_value.EXISTS ( l_key )) THEN
5606 
5607            RETURN h_psnid_propertyid_value ( l_key );
5608 
5609        END IF;
5610 
5611        IF ( h_propertyid_defvalue.EXISTS ( l_property_id )) THEN
5612 
5613            l_def_value := h_propertyid_defvalue ( l_property_id );
5614 
5615        ELSE
5616 
5617            get_user_info ( p_property_id, l_data_type, l_def_value );
5618 
5619        END IF;
5620 
5621        SELECT NVL ( TO_CHAR( data_num_value ), data_value ) BULK COLLECT INTO l_tab
5622          FROM cz_ps_prop_vals
5623         WHERE ps_node_id = p_node_id
5624           AND property_id = p_property_id
5625           AND deleted_flag = '0';
5626 
5627        IF ( l_tab.COUNT = 0 AND p_item_id IS NOT NULL ) THEN
5628 
5629            SELECT NVL( TO_CHAR ( property_num_value ), property_value ) BULK COLLECT INTO l_tab
5630              FROM cz_item_property_values
5631             WHERE property_id = p_property_id
5632               AND item_id = p_item_id
5633               AND deleted_flag = '0';
5634 
5635            IF ( l_tab.COUNT = 0 )THEN
5636 
5637                SELECT NULL BULK COLLECT INTO l_tab
5638                  FROM cz_item_type_properties t, cz_item_masters m
5639                 WHERE m.item_id = p_item_id
5640                   AND m.deleted_flag = '0'
5641                   AND t.deleted_flag = '0'
5642                   AND t.property_id = p_property_id
5643                   AND t.item_type_id = m.item_type_id;
5644 
5645            END IF;
5646        END IF;
5647 
5648        IF ( l_tab.COUNT = 0 ) THEN
5649            -- Property ^PROP_NAME is not defined for node ^NODE_NAME.  Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
5650            report_and_raise_rule_warning(
5651                 p_text => CZ_UTILS.GET_TEXT( CZ_FCE_W_NO_PROPERTY_FOR_NODE,
5652                     'PROP_NAME', CZ_FCE_COMPILE_UTILS.GET_PROPERTY_PATH(l_property_id),
5653                     'NODE_NAME', CZ_FCE_COMPILE_UTILS.GET_NODE_PATH(p_node_id,
5654                                   ps_node_id_table_to_string(
5655                                     build_complete_path(p_node_id, p_expl_id) ) ),
5656                     'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
5657                     'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
5658                 p_warning_location => 'get_user_value');
5659        END IF;
5660 
5661        h_psnid_propertyid_value ( l_key ) := NVL ( l_tab ( 1 ), l_def_value );
5662 
5663        IF ( h_psnid_propertyid_value ( l_key ) IS NULL ) THEN
5664             -- 'Property ^PROP_NAME has no value for node ^NODE_NAME. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
5665            report_and_raise_rule_warning(
5666                 p_text => CZ_UTILS.GET_TEXT( CZ_FCE_W_PROPERTY_NULL_VALUE,
5667                     'PROP_NAME', CZ_FCE_COMPILE_UTILS.GET_PROPERTY_PATH(l_property_id),
5668                     'NODE_NAME', CZ_FCE_COMPILE_UTILS.GET_NODE_PATH(p_node_id,
5669                                   ps_node_id_table_to_string(
5670                                     build_complete_path(p_node_id, p_expl_id) ) ),
5671                     'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
5672                     'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
5673                 p_warning_location => 'get_user_value');
5674 
5675        END IF;
5676 
5677        RETURN h_psnid_propertyid_value ( l_key );
5678 
5679      END get_user_value;
5680      ----------------------------------------------------------------------------------
5681      PROCEDURE get_property_info ( p_property_id   IN NUMBER
5682                                  , x_data_type     IN OUT NOCOPY NUMBER
5683                                  , x_def_value     IN OUT NOCOPY VARCHAR2
5684                                  ) IS
5685      BEGIN
5686 
5687         IF ( get_property_type ( p_property_id ) = h_exprtypes ('property')) THEN
5688 
5689            get_user_info ( p_property_id, x_data_type, x_def_value );
5690 
5691         ELSE
5692 
5693            get_static_info ( p_property_id, x_data_type );
5694 
5695         END IF;
5696      END get_property_info;
5697      ----------------------------------------------------------------------------------
5698      FUNCTION get_property_value ( p_property_id   IN NUMBER
5699                                  , p_node_id       IN NUMBER
5700                                  , p_expl_id       IN NUMBER
5701                                  )
5702      RETURN VARCHAR2 IS
5703      BEGIN
5704 
5705         IF ( get_property_type ( p_property_id ) = h_exprtypes ('property')) THEN
5706 
5707            RETURN get_user_value ( p_property_id, p_node_id, p_expl_id, t_psn_itemid ( h_psnid_backindex ( TO_CHAR ( p_node_id ))));
5708 
5709         ELSE
5710 
5711            RETURN get_static_value ( p_property_id, p_node_id );
5712 
5713         END IF;
5714      END get_property_value;
5715      ----------------------------------------------------------------------------------
5716      --For operators with one operand (totext, not, neg), p_left_operand is used.
5717      -- Scope: compile_constraints
5718      FUNCTION parse_operator ( p_left_operand   IN VARCHAR2
5719                              , p_operator       IN PLS_INTEGER
5720                              , p_right_operand  IN VARCHAR2
5721                              ) RETURN VARCHAR2 IS
5722      BEGIN
5723 
5724         IF ( p_operator IN
5725                 ( h_templates ('and')
5726                 , h_templates ('or')
5727                 , h_templates ('equals')
5728                 , h_templates ('notequals')
5729                 , h_templates ('gt')
5730                 , h_templates ('lt')
5731                 , h_templates ('ge')
5732                 , h_templates ('le')
5733                 , h_templates ('add')
5734                 , h_templates ('subtract')
5735                 , h_templates ('multiply')
5736                 , h_templates ('div')
5737                 , h_templates('textequals')
5738                 , h_templates('textnotequals')
5739                 )) THEN
5740 
5741            RETURN '(' || p_left_operand || h_template_tokens ( p_operator ) || p_right_operand || ')';
5742 
5743         ELSIF ( p_operator IN
5744                   ( h_templates ('totext')
5745                   , h_templates ('not')
5746                   , h_templates ('neg')
5747                   )) THEN
5748 
5749            RETURN '(' || h_template_tokens ( p_operator ) || '(' || p_left_operand || '))';
5750 
5751         ELSIF ( p_operator = h_templates ('doesnotbeginwith')) THEN
5752 
5753            RETURN '(' || p_left_operand || ' NOT LIKE ' || p_right_operand || '||''%'')';
5754 
5755         ELSIF ( p_operator = h_templates ('doesnotendwith')) THEN
5756 
5757            RETURN '(' || p_left_operand || ' NOT LIKE ''%''||' || p_right_operand || ')';
5758 
5759         ELSIF ( p_operator = h_templates ('doesnotcontain')) THEN
5760 
5761            RETURN '(' || p_left_operand || ' NOT LIKE ''%''||' || p_right_operand || '||''%'')';
5762 
5763         ELSIF ( p_operator = h_templates ('notlike')) THEN
5764 
5765            RETURN '(' || p_left_operand || ' NOT LIKE ' || p_right_operand || ')';
5766 
5767         ELSIF ( p_operator = h_templates ('concatenate')) THEN
5768 
5769            RETURN p_left_operand || '||' || p_right_operand;
5770 
5771         ELSIF ( p_operator = h_templates ('beginswith')) THEN
5772 
5773            RETURN '(' || p_left_operand || ' LIKE ' || p_right_operand || '||''%'')';
5774 
5775         ELSIF ( p_operator = h_templates ('endswith')) THEN
5776 
5777            RETURN '(' || p_left_operand || ' LIKE ''%''||' || p_right_operand || ')';
5778 
5779         ELSIF ( p_operator = h_templates ('contains')) THEN
5780 
5781            RETURN '(' || p_left_operand || ' LIKE ''%''||' || p_right_operand || '||''%'')';
5782 
5783         ELSIF ( p_operator = h_templates ('like')) THEN
5784 
5785            RETURN '(' || p_left_operand || ' LIKE ' || p_right_operand || ')';
5786 
5787         ELSIF ( p_operator = h_templates ('matches')) THEN
5788 
5789            RETURN '(' || p_left_operand || ' LIKE ' || p_right_operand || ')';
5790 
5791         END IF;
5792      END parse_operator;
5793      ----------------------------------------------------------------------------------
5794      -- Scope: compile_constraints
5795      FUNCTION build_executable ( p_count IN PLS_INTEGER, p_parsed IN VARCHAR2 ) RETURN VARCHAR2 IS
5796 
5797         l_open         VARCHAR2(32000);
5798         l_body         VARCHAR2(32000);
5799         l_close        VARCHAR2(32000);
5800 
5801         l_value        VARCHAR2(4000);
5802 
5803      BEGIN
5804 
5805         FOR i IN 1..p_count LOOP
5806 
5807            l_value := TO_CHAR ( i );
5808 
5809            l_open := l_open || ' FOR i' || l_value || ' IN 1..cz_fce_compile.s_(' || l_value || ') LOOP';
5810            l_body := l_body || ' cz_fce_compile.c_.combinations(l)(' || l_value || '):=cz_fce_compile.o_(' || l_value || ')(i' || l_value || ');';
5811            l_close := l_close || 'END LOOP;';
5812 
5813         END LOOP;
5814 
5815         --Example of an executable block that will be constructed for the following WHERE clause
5816         --(passed in p_condition).
5817 
5818         --#<optimization> See bug #6531346 for possible optimization.
5819 
5820         --WHERE #x.Property("p1") = #y.Property("p2")
5821         --  AND #x.Property("p1") = #z.Property("p2")
5822         --  AND #z.Name() BEGINSWITH "abc"
5823         --  AND #x.Property("p3") = TRUE
5824         --  AND (2 = 2)
5825 
5826         --Resulting code (note that parser has rewritten (2 = 2) as TRUE):
5827 
5828         --DECLARE
5829         --  l PLS_INTEGER:=1;
5830         --BEGIN
5831         --  FOR i1 IN 1..cz_fce_compile.s_(1) LOOP
5832         --  FOR i2 IN 1..cz_fce_compile.s_(2) LOOP
5833         --  FOR i3 IN 1..cz_fce_compile.s_(3) LOOP
5834         --     IF((cz_fce_compile.n_(1)(i1)(1)=cz_fce_compile.n_(2)(i2)(2))AND
5835         --        (cz_fce_compile.n_(1)(i1)(1)=cz_fce_compile.n_(3)(i3)(2))AND
5836         --        (cz_fce_compile.t_(3)(i3)(3) LIKE 'abc%')AND
5837         --        (cz_fce_compile.b_(1)(i1)(4)=1)AND(TRUE))THEN
5838         --           cz_fce_compile.c_.combinations(l)(1):=cz_fce_compile.o_(1)(i1);
5839         --           cz_fce_compile.c_.combinations(l)(2):=cz_fce_compile.o_(2)(i2);
5840         --           cz_fce_compile.c_.combinations(l)(3):=cz_fce_compile.o_(3)(i3);
5841         --           l := l + 1;
5842         --     END IF;
5843         --  END LOOP;
5844         --  END LOOP;
5845         --  END LOOP;
5846         --END;
5847 
5848         RETURN 'DECLARE l PLS_INTEGER:=1;BEGIN'
5849                || l_open ||
5850                ' IF(' || NVL ( p_parsed, 'TRUE' ) || ')THEN'
5851                || l_body ||
5852                'l:=l+1;END IF;'
5853                || l_close ||
5854               'END;';
5855      END;
5856      ----------------------------------------------------------------------------------
5857      -- Scope: compile_constraints
5858      PROCEDURE generate_user_property ( j IN PLS_INTEGER
5859                                       , p_input_context IN expression_context
5860                                       , x_output_context IN OUT NOCOPY expression_context ) IS
5861 
5862         l_property_id     NUMBER;
5863         l_data_type       NUMBER;
5864         l_def_value       VARCHAR2(4000);
5865         l_value           VARCHAR2(4000);
5866         l_expr_id         VARCHAR2(4000);
5867         l_index           PLS_INTEGER;
5868 
5869         l_input_context   expression_context;
5870 
5871      BEGIN
5872 
5873         l_property_id := t_exp_propertyid ( h_exprid_childrenindex ( TO_CHAR ( t_exp_exprnodeid ( j ))));
5874         get_user_info ( l_property_id, l_data_type, l_def_value );
5875 
5876         l_value := get_user_value ( l_property_id
5877                                   , t_exp_psnodeid ( j )
5878                                   , t_exp_modelrefexplid ( j )
5879                                   , t_psn_itemid ( h_psnid_backindex ( TO_CHAR ( t_exp_psnodeid ( j ))))
5880                                   );
5881 
5882         IF ( l_data_type = h_datatypes('text')) THEN
5883 
5884             IF ( numeric_context ( j, p_input_context.context_type )) THEN
5885 
5886                --This property is used as a numeric property but has data type 'text', for example,
5887                --bom properties imported without data type resolution. In this case, all values of
5888                --this property are assumed to be convertible to numbers. If this is not true, this
5889                --will cause problems later in push_constant_expr where will be actually converted.
5890 
5891                --We can add the check for number here, and also see if it is decimal or integer for
5892                --better resolution of data type.
5893 
5894                l_data_type := h_datatypes ('decimal');
5895 
5896             ELSE
5897 
5898                --#<should never happen>
5899                -- 'Found property with the id "^PROP_ID" as text property. Rules cannot handle text properties. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
5900                report_and_raise_rule_sys_warn(
5901                 p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_NO_TEXT_PROP,
5902                         'PROP_ID', l_property_id ),
5903                 p_warning_location => 'generate_user_property');
5904 
5905             END IF;
5906         END IF;
5907 
5908         --#<problem>
5909         --Note that the input context of this procedure is not passed down to generate_literal.
5910         --The local context variable is not used in any other way, so it seems that it's been
5911         --created specifically for this purpose. Not sure if this was done intentionally, need
5912         --to keep an eye on it.
5913 
5914         generate_literal ( j, l_value, l_data_type, l_input_context, x_output_context );
5915 
5916      END generate_user_property;
5917      ----------------------------------------------------------------------------------
5918      -- Scope: compile_constraints
5919      PROCEDURE generate_selection_property ( j IN PLS_INTEGER
5920                                            , p_property_id IN NUMBER
5921                                            , p_input_context IN expression_context
5922                                            , x_output_context IN OUT NOCOPY expression_context
5923                                            ) IS
5924 
5925         l_return            PLS_INTEGER;
5926         l_index             PLS_INTEGER;
5927 
5928         l_is_bom            BOOLEAN;
5929 
5930      BEGIN
5931 
5932         IF ( h_quantities.EXISTS ( p_property_id )) THEN
5933 
5934            generate_numeric_options ( j, p_property_id, TRUE, p_input_context, x_output_context );
5935            RETURN;
5936 
5937         END IF;
5938 
5939         l_index := h_psnid_backindex ( TO_CHAR ( t_exp_psnodeid ( j )));
5940         l_is_bom := is_bom_node ( l_index );
5941 
5942         l_return := generate_path ( t_exp_psnodeid ( j ), t_exp_modelrefexplid ( j ), p_input_context, x_output_context );
5943 
5944         IF ( l_return = const_quantifier_created ) THEN
5945 
5946            emit_invokevirtual('IInstanceQuantifier.getExprFromInstance(IExprDef)');
5947 
5948         END IF;
5949 
5950         --This procedure is called in generate_selection only when the property applied
5951         --to selection, is one of Quantity(), State() or Value(). In case of Value() we
5952         --just generate the node, which is already done above. So, here we only have to
5953         --generate State().
5954 
5955         IF ( l_is_bom ) THEN
5956 
5957            apply_bom_property ('IBomDef.getOCCardSet()');
5958 
5959         END IF;
5960 
5961         IF ( p_property_id = h_templates ('state')) THEN
5962 
5963            any_option_selected ();
5964 
5965         END IF;
5966 
5967         IF ( l_return = const_resourcesum_required ) THEN
5968 
5969            emit_invokevirtual('IPortExprDef.sum(INumExprDef)');
5970 
5971         END IF;
5972      END generate_selection_property;
5973      ----------------------------------------------------------------------------------
5974      -- Scope: compile_constraints
5975      PROCEDURE generate_selection_object ( p_node_id          IN NUMBER
5976                                          , p_expl_id          IN NUMBER
5977                                          , p_data_type        IN NUMBER
5978                                          , p_property_values  IN type_numbertable_hashtable
5979                                          , p_input_context    IN expression_context
5980                                          , x_output_context   IN OUT NOCOPY expression_context
5981                                          ) IS
5982 
5983         l_return   PLS_INTEGER;
5984         l_count    PLS_INTEGER;
5985         l_value    VARCHAR2(4000);
5986 
5987      BEGIN
5988 
5989         IF ( p_property_values.COUNT > 2 ) THEN
5990 
5991            --If there are more than two distinct property values, we will call 'sum' later,
5992            --and need model def for that.
5993 
5994            aload_model_def ( p_component_id );
5995 
5996         END IF;
5997 
5998         l_return := generate_path ( p_node_id, p_expl_id, p_input_context, x_output_context );
5999 
6000         IF ( h_psnid_detailedtype ( TO_CHAR ( p_node_id )) = h_psntypes ('optionfeature')) THEN
6001 
6002           IF ( l_return = const_quantifier_created ) THEN emit_invokevirtual('IInstanceQuantifier.getExprFromInstance(IExprDef)'); END IF;
6003 
6004           astore_local_variable ( 'var' );
6005 
6006           l_value := p_property_values.FIRST;
6007 
6008           WHILE ( l_value IS NOT NULL ) LOOP
6009 
6010              l_count := p_property_values ( l_value ).COUNT;
6011              aload_local_variable ( 'var' );
6012 
6013              FOR i IN 1..l_count LOOP
6014 
6015                 push_variable_name ( p_property_values ( l_value )( i ));
6016 
6017              END LOOP;
6018 
6019              IF ( l_count = 1 ) THEN
6020 
6021                 --Just one option, generate 'contains' instead of 'intersects'.
6022 
6023                 emit_invokevirtual ('ISetExprDef.contains(Object)');
6024 
6025              ELSE
6026 
6027                 create_array ( l_count, h_javatypes ('Object'));
6028                 populate_array ( l_count );
6029                 emit_invokevirtual ('ISetExprDef.intersects(Object[])');
6030 
6031              END IF;
6032 
6033              --If the property value is 1, there is no need to multiply.
6034 
6035              IF ( TO_NUMBER ( l_value ) <> 1 ) THEN
6036 
6037                 push_decimal_constant ( TO_NUMBER ( l_value ));
6038                 emit_invokevirtual ( CASE p_data_type WHEN h_datatypes ('decimal') THEN 'INumExprDef.prod(double)' ELSE 'INumExprDef.prod(int)' END );
6039 
6040              END IF;
6041 
6042              l_value := p_property_values.NEXT ( l_value );
6043 
6044           END LOOP;
6045 
6046         ELSIF ( h_psnid_detailedtype ( TO_CHAR ( p_node_id )) = h_psntypes ('bomoptionclass')) THEN
6047 
6048           astore_local_variable ( 'var' );
6049 
6050           --If there is an instance quantifier, it is now on top of stack. Also need to store.
6051 
6052           IF ( l_return = const_quantifier_created ) THEN astore_local_variable ( 'iq' ); END IF;
6053 
6054           l_value := p_property_values.FIRST;
6055 
6056           WHILE ( l_value IS NOT NULL ) LOOP
6057 
6058              l_count := p_property_values ( l_value ).COUNT;
6059 
6060              FOR i IN 1..l_count LOOP
6061 
6062                IF ( l_return = const_quantifier_created ) THEN aload_local_variable ( 'iq' ); END IF;
6063                aload_local_variable ( 'var' );
6064 
6065                push_variable ( p_property_values ( l_value )( i ), 'ISingletonExprDef');
6066                emit_invokevirtual ('ISingletonExprDef.getVarRef(IExprDef)');
6067 
6068                apply_bom_logical_context ( p_property_values ( l_value )( i ), l_return );
6069 
6070              END LOOP;
6071 
6072              invoke_anyalltrue ( h_templates ('anytrue'), l_count );
6073 
6074              --If the property value is 1, there is no need to multiply.
6075 
6076              IF ( TO_NUMBER ( l_value ) <> 1 ) THEN
6077 
6078                 push_decimal_constant ( TO_NUMBER ( l_value ));
6079                 emit_invokevirtual ( CASE p_data_type WHEN h_datatypes ('decimal') THEN 'INumExprDef.prod(double)' ELSE 'INumExprDef.prod(int)' END );
6080 
6081              END IF;
6082 
6083              l_value := p_property_values.NEXT ( l_value );
6084 
6085           END LOOP;
6086 
6087         ELSE
6088             -- '"Selection()" property is allowed only for Option Feature or BOM Option Class. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
6089             report_and_raise_rule_sys_warn(
6090                 p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_SELECT_PROP_NOTALLOW ),
6091                 p_warning_location => 'generate_selection_object');
6092 
6093         END IF;
6094 
6095         sum_numeric ( p_property_values.COUNT );
6096 
6097      END generate_selection_object;
6098      ----------------------------------------------------------------------------------
6099      -- Scope: compile_constraints
6100      PROCEDURE generate_text_comparison ( p_operator IN PLS_INTEGER
6101                                         , p_side IN PLS_INTEGER
6102                                         , p_input_context IN expression_context
6103                                         , x_output_context IN OUT NOCOPY expression_context
6104                                         ) IS
6105 
6106         t_property_values   type_numbertable_hashtable;
6107 
6108      BEGIN
6109 
6110         EXECUTE IMMEDIATE build_executable ( 2, parse_operator ( 'cz_fce_compile.t_(1)(i1)(1)', p_operator, 'cz_fce_compile.t_(2)(i2)(1)'));
6111 
6112         IF ( p_side = 0 ) THEN
6113 
6114            --There is no selection, both sides are text literals, just push either true or false.
6115 
6116            push_constant_expr ( CASE c_.combinations.COUNT WHEN 0 THEN '0' ELSE '1' END, h_datatypes ('boolean'));
6117 
6118         ELSE
6119 
6120            --We populate the table in such a way, that the following procedure will just generate
6121            --intersect of all options or bom children. The key '1' is used so that this intersect
6122            --would not be multiplied by anything.
6123 
6124            FOR i IN 1..c_.combinations.COUNT LOOP
6125 
6126               t_property_values ( '1' )( i ) := c_.combinations ( i )( p_side ).ps_node_id;
6127 
6128            END LOOP;
6129 
6130            generate_selection_object ( c_.participants ( p_side ).ps_node_id
6131                                      , c_.participants ( p_side ).model_ref_expl_id
6132                                      , h_datatypes ('text')
6133                                      , t_property_values
6134                                      , p_input_context, x_output_context );
6135         END IF;
6136      END generate_text_comparison;
6137      ----------------------------------------------------------------------------------
6138      -- Scope: compile_constraints
6139      PROCEDURE generate_selection ( j IN PLS_INTEGER
6140                                   , p_property_id IN NUMBER
6141                                   , p_input_context IN expression_context
6142                                   , x_output_context IN OUT NOCOPY expression_context
6143                                   ) IS
6144 
6145         l_property_id       NUMBER := p_property_id;
6146         l_data_type         NUMBER;
6147         l_value             VARCHAR2(4000);
6148         l_count             PLS_INTEGER;
6149 
6150         l_text_property     BOOLEAN := FALSE;
6151         l_side              PLS_INTEGER;
6152 
6153         t_children          type_iteratornode_table;
6154         t_property_values   type_numbertable_hashtable;
6155 
6156      BEGIN
6157 
6158         IF ( t_exp_psnodeid ( j ) IS NULL ) THEN
6159            -- '"Selection()" property is allowed only for Option Feature or BOM Option Class. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
6160            report_and_raise_rule_sys_warn(
6161                 p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_SELECT_PROP_NOTALLOW ),
6162                 p_warning_location => 'generate_selection');
6163 
6164         END IF;
6165 
6166         IF ( l_property_id IS NULL ) THEN
6167 
6168            --No explicitly specified property, derive one from the context.
6169 
6170            IF ( logical_context ( j, p_input_context.context_type )) THEN
6171 
6172               l_property_id := h_templates ('state');
6173 
6174            ELSIF ( numeric_context ( j, p_input_context.context_type )) THEN
6175 
6176               l_property_id := h_templates ('quantity');
6177 
6178            ELSE
6179               -- 'Invalid context found for applying default property. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
6180               report_and_raise_rule_sys_warn(
6181                 p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_DEFPROP_INVAL_CTX ),
6182                 p_warning_location => 'generate_selection');
6183 
6184            END IF;
6185 
6186            h_propertyid_type ( TO_CHAR ( l_property_id )) := h_exprtypes ('systemproperty');
6187 
6188         END IF;
6189 
6190         IF ( h_quantities.EXISTS ( l_property_id ) OR l_property_id IN ( h_templates ('state'), h_templates ('value'))) THEN
6191 
6192            generate_selection_property ( j, l_property_id, p_input_context, x_output_context );
6193            RETURN;
6194 
6195         ELSIF ( l_property_id IN ( h_templates ('name'), h_templates ('description'))) THEN
6196 
6197            get_static_info ( l_property_id, l_data_type );
6198 
6199         ELSIF ( get_property_type ( l_property_id ) = h_exprtypes ('property')) THEN
6200 
6201            get_user_info ( l_property_id, l_data_type, l_value );
6202 
6203         ELSE
6204            -- 'Invalid system property is used with the "Selection()" operator. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
6205            report_and_raise_rule_sys_warn(
6206                 p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_INVAL_SPROP_SELECT ),
6207                 p_warning_location => 'generate_selection');
6208 
6209         END IF;
6210 
6211         t_children := explode_node_children ( t_exp_psnodeid ( j ), t_exp_modelrefexplid ( j ), TRUE );
6212 
6213         IF ( l_data_type = h_datatypes ('text') OR p_input_context.context_type = const_context_selection ) THEN
6214 
6215            --This will be 'text' selection, prepare the data structures.
6216 
6217            l_side := s_.COUNT + 1;
6218            s_( l_side ) := t_children.COUNT;
6219 
6220            c_.participants ( l_side ).ps_node_id := t_exp_psnodeid ( j );
6221            c_.participants ( l_side ).model_ref_expl_id := t_exp_modelrefexplid ( j );
6222 
6223            l_text_property := TRUE;
6224 
6225         END IF;
6226 
6227         --All distinct property values are keys to the tables of all options that have these values.
6228 
6229         FOR i IN 1..t_children.COUNT LOOP
6230 
6231            l_value := get_property_value ( l_property_id, t_children ( i ).ps_node_id, t_children ( i ).model_ref_expl_id );
6232 
6233            IF ( l_value IS NULL ) THEN
6234               -- 'Property ^PROP_NAME has no value for node ^NODE_NAME. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
6235               report_and_raise_rule_warning(
6236                 p_text => CZ_UTILS.GET_TEXT( CZ_FCE_W_PROPERTY_NULL_VALUE,
6237                     'PROP_NAME', CZ_FCE_COMPILE_UTILS.GET_PROPERTY_PATH(l_property_id),
6238                     'NODE_NAME', CZ_FCE_COMPILE_UTILS.GET_NODE_PATH(t_children ( i ).ps_node_id,
6239                         ps_node_id_table_to_string(
6240                                     build_complete_path(t_children ( i ).ps_node_id, t_children ( i ).model_ref_expl_id) ) ),
6241                     'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
6242                     'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
6243                 p_warning_location => 'generate_selection');
6244 
6245            END IF;
6246 
6247            IF ( l_text_property ) THEN
6248 
6249               --Populate the data structures that will be used for generation.
6250 
6251               o_( l_side )( i ).ps_node_id := t_children ( i ).ps_node_id;
6252               o_( l_side )( i ).model_ref_expl_id := t_children ( i ).model_ref_expl_id;
6253 
6254               t_( l_side )( i )( 1 ) := l_value;
6255 
6256            ELSE
6257 
6258               IF ( NOT t_property_values.EXISTS ( l_value )) THEN
6259 
6260                  t_property_values ( l_value )( 1 ) := t_children ( i ).ps_node_id;
6261 
6262               ELSE
6263 
6264                  l_count := t_property_values ( l_value ).COUNT + 1;
6265                  t_property_values ( l_value )( l_count ) := t_children ( i ).ps_node_id;
6266 
6267               END IF;
6268            END IF;
6269         END LOOP;
6270 
6271         IF ( NOT l_text_property ) THEN
6272 
6273            --Generate the 'numeric' selection object.
6274 
6275            generate_selection_object ( t_exp_psnodeid ( j )
6276                                      , t_exp_modelrefexplid ( j )
6277                                      , l_data_type
6278                                      , t_property_values
6279                                      , p_input_context, x_output_context );
6280 
6281         END IF;
6282      END generate_selection;
6283      ----------------------------------------------------------------------------------
6284      -- Scope: compile_constraints
6285      -- Returns the data type of the given signature argument.
6286 
6287      FUNCTION get_signature_arg_info ( p_arg_index    IN NUMBER
6288                                      , p_signature_id IN NUMBER
6289                                      , x_mutable      IN OUT NOCOPY VARCHAR2
6290                                      , x_collection   IN OUT NOCOPY VARCHAR2
6291                                      ) RETURN NUMBER IS
6292 
6293           l_data_type  cz_signature_arguments.data_type%TYPE;
6294 
6295       BEGIN
6296 
6297           SELECT data_type, mutable_flag, collection_flag INTO l_data_type, x_mutable, x_collection
6298             FROM cz_signature_arguments
6299            WHERE deleted_flag = '0'
6300              AND argument_signature_id = p_signature_id
6301              AND argument_index = p_arg_index;
6302 
6303           RETURN l_data_type;
6304 
6305       EXCEPTION
6306         WHEN OTHERS THEN
6307 
6308           report_and_raise_rule_sys_warn (
6309                 p_text => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SW_RE_ENSARG_NO_DTYPE,
6310                         'ARG_IX', p_arg_index,
6311                         'SIGNATURE_ID', p_signature_id ),
6312                 p_warning_location => 'get_signature_arg_info');
6313 
6314           RETURN NULL;
6315 
6316       END get_signature_arg_info;
6317       ---------------------------------------------------------------------------------------
6318       -- Scope: compile_constraints
6319       -- Returns TRUE when the given property associated with the given node id is valid, otherwise
6320       -- returns FALSE.
6321 
6322       FUNCTION is_valid_property ( j             IN PLS_INTEGER
6323                                  , p_ps_node_id  IN NUMBER
6324                                  , p_property_id IN NUMBER
6325                                  ) RETURN BOOLEAN IS
6326 
6327           l_null        PLS_INTEGER;
6328           l_data_type   cz_signature_arguments.data_type%TYPE;
6329           l_mutable     cz_signature_arguments.mutable_flag%TYPE;
6330           l_collection  cz_signature_arguments.collection_flag%TYPE;
6331 
6332           l_key         VARCHAR2(4000);
6333 
6334       BEGIN
6335 
6336          l_key := TO_CHAR ( p_ps_node_id ) || ':' || TO_CHAR ( p_property_id );
6337 
6338          IF ( NOT h_psnid_propid_isvalid.EXISTS ( l_key )) THEN
6339 
6340            IF ( t_exp_paramindex ( j ) IS NULL OR t_exp_paramsignatureid ( j ) IS NULL ) THEN
6341 
6342               --Some of the upgraded rules may not have param_index and param_signature_id populated. However, upgraded
6343               --rules are not real statement rules, so they are not supposed to have any user error in them and in this
6344               --case the verification is not required.
6345 
6346               h_psnid_propid_isvalid ( l_key ) := TRUE;
6347 
6348            ELSE
6349 
6350              BEGIN
6351 
6352                l_data_type := get_signature_arg_info ( t_exp_paramindex ( j ), t_exp_paramsignatureid ( j ), l_mutable, l_collection );
6353 
6354                SELECT NULL INTO l_null
6355                  FROM cz_rul_typedpsn_v psn,
6356                       cz_conversion_rels_v cnv,
6357                       cz_system_property_rels_v rel,
6358                       cz_system_properties_v sys,
6359                       cz_conversion_rels_v cnv2
6360                 WHERE psn.detailed_type_id = cnv.object_type
6361                   AND cnv.subject_type = rel.subject_type
6362                   AND rel.object_type = sys.rule_id
6363                   AND rel.rel_type_code = 'SYS'
6364                   AND sys.data_type = cnv2.object_type
6365                   AND psn.ps_node_id = p_ps_node_id
6366                   AND sys.rule_id = p_property_id
6367                   AND sys.mutable_flag >= l_mutable
6368 --Note: Collection flag filter is removed, to allow rules like AddsTo(OptionFeature.options(), Total).
6369 --                AND sys.collection_flag <= l_collection
6370                   AND cnv2.subject_type = l_data_type;
6371 
6372                h_psnid_propid_isvalid ( l_key ) := TRUE;
6373 
6374              EXCEPTION
6375                 WHEN NO_DATA_FOUND THEN
6376                    h_psnid_propid_isvalid ( l_key ) := FALSE;
6377                 WHEN TOO_MANY_ROWS THEN
6378                    h_psnid_propid_isvalid ( l_key ) := TRUE;
6379                 WHEN OTHERS THEN
6380                    RAISE;
6381              END;
6382            END IF;
6383          END IF;
6384 
6385          RETURN h_psnid_propid_isvalid ( l_key );
6386 
6387       END is_valid_property;
6388      ---------------------------------------------------------------------------------------
6389      -- Scope: compile_constraints
6390      PROCEDURE generate_structure_node ( j IN PLS_INTEGER
6391                                        , p_input_context IN expression_context
6392                                        , x_output_context IN OUT NOCOPY expression_context ) IS
6393 
6394        l_expr_id       VARCHAR2(4000);
6395        l_property_id   NUMBER;
6396        l_index         PLS_INTEGER;
6397        l_target_key    VARCHAR2(4000);
6398 
6399     BEGIN
6400 
6401        IF ( p_input_context.context_type = const_context_target ) THEN
6402 
6403           --This has been moved here from generate_path because when the target exists, we need
6404           --to just populate the output context and exit and not apply any context that is done
6405           --usually after generate_path (for example, see generate_node).
6406 
6407           --In general, this key should contain more information about the target and the rule,
6408           --including rule's effecitivity and usage, and target's properties.
6409 
6410           l_target_key := TO_CHAR ( t_exp_psnodeid ( j )) || ':' || TO_CHAR ( t_exp_modelrefexplid ( j ));
6411 
6412           IF ( h_acc_targets.EXISTS ( l_target_key )) THEN
6413 
6414              --Target has been generated before, just return. Context is changed to generic to
6415              --indicate that.
6416 
6417              x_output_context.context_type := const_context_generic;
6418              x_output_context.context_num_data := h_acc_targets ( l_target_key );
6419 
6420              RETURN;
6421           END IF;
6422        END IF;
6423 
6424        l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
6425 
6426        IF ( NOT h_exprid_childrenindex.EXISTS ( l_expr_id )) THEN
6427 
6428           generate_node ( j, p_input_context, x_output_context );
6429 
6430        ELSE
6431 
6432           l_index := h_exprid_childrenindex ( l_expr_id );
6433 
6434           IF ( t_exp_exprtype ( l_index ) = h_exprtypes ('property')) THEN
6435 
6436               generate_user_property ( j, p_input_context, x_output_context );
6437 
6438           ELSIF ( t_exp_templateid ( l_index ) = h_templates ('selection')) THEN
6439 
6440               l_index := l_index + 1;
6441 
6442               IF ( t_exp_exprparentid.EXISTS ( l_index ) AND t_exp_exprparentid ( l_index ) = t_exp_exprnodeid ( j )) THEN
6443 
6444                  l_property_id := get_property_id ( l_index );
6445 
6446               END IF;
6447 
6448               generate_selection ( j, l_property_id, p_input_context, x_output_context );
6449 
6450           ELSE
6451 
6452              l_property_id := t_exp_templateid ( l_index );
6453 
6454              IF ( l_property_id IN ( h_templates ('mininstances'), h_templates ('maxinstances')) OR
6455                   ( NOT is_valid_property ( j, t_exp_psnodeid ( j ), l_property_id ))) THEN
6456 
6457               --#Dave Kulik, 10/05/07 regarding Min/MaxInstances:
6458 
6459               --The plan has always been to disallow operations directly on the mins and maxes. They would just
6460               --be side-effected by rules like "node.InstanceCount() > x". So if you want to use accumulator
6461               --rules you have a couple of options.  You could just write "x AddsTo node.InstanceCount()". Or,
6462               --if you wanted to constrain the domain of InstanceCount without affecting it directly and
6463               --immediately, you could maintain a couple of intermediate variables using accumulator rules and
6464               --constrain InstanceCount relative to those.
6465 
6466               --Property ^PROP_NAME is invalid for the node ^NODE_NAME. Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
6467 
6468               report_and_raise_rule_warning (
6469                   p_text => CZ_UTILS.GET_TEXT (
6470                           CZ_FCE_W_INVALID_PROPERTY,
6471                           'PROP_NAME', CZ_FCE_COMPILE_UTILS.GET_PROPERTY_PATH ( l_property_id ),
6472                           'NODE_NAME', CZ_FCE_COMPILE_UTILS.GET_NODE_PATH ( t_exp_psnodeid ( j ),
6473                                    ps_node_id_table_to_string (
6474                                     build_complete_path ( t_exp_psnodeid ( j ), t_exp_modelrefexplid( j )))),
6475                           'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name ),
6476                           'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH( p_component_id, p_model_path )),
6477                 p_warning_location => 'generate_structure_node');
6478 
6479             END IF;
6480 
6481             IF ( l_property_id = h_templates ('options')) THEN
6482 
6483                 generate_options ( j, p_input_context, x_output_context );
6484 
6485              ELSE
6486 
6487                 generate_system_property ( l_property_id, t_exp_psnodeid ( j ), t_exp_modelrefexplid ( j ), p_input_context, x_output_context );
6488 
6489              END IF;
6490           END IF;
6491        END IF;
6492     END generate_structure_node;
6493      ----------------------------------------------------------------------------------
6494      -- Scope: compile_constraints
6495      PROCEDURE generate_logic_template ( j IN PLS_INTEGER
6496                                        , p_input_context IN expression_context
6497                                        , x_output_context IN OUT NOCOPY expression_context
6498                                        ) IS
6499 
6500         l_expr_id             VARCHAR2(4000);
6501         l_exprnode_id         NUMBER;
6502         l_index               PLS_INTEGER;
6503         l_expr_index          PLS_INTEGER;
6504 
6505         t_lhs_operator        type_integer_table;
6506         t_lhs_index           type_integer_table;
6507         t_logic_operator      type_integer_table;
6508         t_rhs_operator        type_integer_table;
6509         t_rhs_index           type_integer_table;
6510 
6511         l_input_context       expression_context;
6512 
6513      BEGIN
6514 
6515         --This procedure implements generation of simple logic rule. The template application
6516         --specifies the following parameters:
6517 
6518         -- param_index = 1: left-hand side AnyTrue or AllTrue operator
6519         -- param_index = 2: left-hand side participant(s)
6520         -- param_index = 3: logic operator
6521         -- param_index = 4: right-hand side AnyTrue or AllTrue operator
6522         -- param_index = 5: right-hand side participant(s)
6523 
6524         l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
6525 
6526         IF ( expr_has_children ( l_expr_id )) THEN
6527 
6528           l_index := h_exprid_childrenindex ( l_expr_id ) - 1;
6529 
6530         ELSE
6531 
6532           report_and_raise_rule_sys_warn (
6533                 p_text => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SW_RE_ENODE_CHILDREN,
6534                             'EXPR_ID', l_expr_id ),
6535                 p_warning_location => 'generate_logic_template');
6536 
6537         END IF;
6538 
6539         --Parse the template application.
6540 
6541         FOR i IN 1..h_exprid_numberofchildren ( l_expr_id ) LOOP
6542 
6543            l_expr_index := l_index + i;
6544 
6545            CASE t_exp_paramindex ( l_expr_index )
6546 
6547                WHEN 1 THEN
6548 
6549                   t_lhs_operator ( t_lhs_operator.COUNT + 1 ) := l_expr_index;
6550 
6551                WHEN 2 THEN
6552 
6553                   t_lhs_index ( t_lhs_index.COUNT + 1 ) := l_expr_index;
6554 
6555                WHEN 3 THEN
6556 
6557                   t_logic_operator ( t_logic_operator.COUNT + 1 ) := t_exp_templateid ( l_expr_index );
6558 
6559                WHEN 4 THEN
6560 
6561                   t_rhs_operator ( t_rhs_operator.COUNT + 1 ) := l_expr_index;
6562 
6563                WHEN 5 THEN
6564 
6565                   t_rhs_index ( t_rhs_index.COUNT + 1 ) := l_expr_index;
6566 
6567            END CASE;
6568         END LOOP;
6569 
6570         --Verify the template application.
6571 
6572         IF ( t_lhs_operator.COUNT <> 1 OR ( NOT h_operators_3.EXISTS ( t_exp_templateid ( t_lhs_operator ( 1 ))))) THEN
6573             -- 'Left-hand side operator is either not-specified or invalid. Logic rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
6574             report_and_raise_rule_sys_warn(
6575                 p_text => GET_NOT_TRANSLATED_TEXT(
6576                         CZ_FCE_SW_LR_MISSING_LHS_OP ),
6577                 p_warning_location => 'generate_logic_template');
6578 
6579         ELSIF ( t_lhs_index.COUNT = 0 ) THEN
6580             -- Right-hand side participants are missing.  Logic rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
6581             report_and_raise_rule_warning(
6582                 p_text => CZ_UTILS.GET_TEXT(
6583                         CZ_FCE_W_LR_MISSING_LHS_PARTS,
6584                         'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
6585                         'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
6586                 p_warning_location => 'generate_logic_template');
6587 
6588         ELSIF ( t_logic_operator.COUNT <> 1 OR ( NOT h_operators_2.EXISTS ( t_logic_operator ( 1 )))) THEN
6589 
6590             report_and_raise_rule_sys_warn(
6591                 p_text => GET_NOT_TRANSLATED_TEXT(
6592                         CZ_FCE_SW_LR_MISSING_LOGIC_OP ),
6593                 p_warning_location => 'generate_logic_template');
6594 
6595         ELSIF ( t_rhs_operator.COUNT <> 1 OR ( NOT h_operators_3.EXISTS ( t_exp_templateid ( t_rhs_operator ( 1 ))))) THEN
6596 
6597             report_and_raise_rule_sys_warn(
6598                 p_text => GET_NOT_TRANSLATED_TEXT(
6599                         CZ_FCE_SW_LR_MISSING_RHS_OP ),
6600                 p_warning_location => 'generate_logic_template');
6601 
6602         ELSIF ( t_rhs_index.COUNT = 0 ) THEN
6603             -- Right-hand side participants are missing.  Logic rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
6604             report_and_raise_rule_warning(
6605                 p_text => CZ_UTILS.GET_TEXT(
6606                         CZ_FCE_W_LR_MISSING_RHS_PARTS,
6607                         'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
6608                         'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
6609                 p_warning_location => 'generate_logic_template');
6610 
6611         END IF;
6612 
6613         l_input_context.context_type := const_context_logical;
6614 
6615         --Need to emulate all participants as children of the AnyTrue or AllTrue operator
6616         --in order to provide context for participants' generation, and to know the exact
6617         --number of arguments to this operator.
6618 
6619         l_exprnode_id := t_exp_exprnodeid ( t_lhs_operator ( 1 ));
6620         l_expr_id := TO_CHAR ( l_exprnode_id );
6621 
6622         h_exprid_numberofchildren ( l_expr_id ) := 0;
6623 
6624         FOR i IN 1..t_lhs_index.COUNT LOOP
6625 
6626             t_exp_exprparentid ( t_lhs_index ( i )) := l_exprnode_id;
6627             h_exprid_numberofchildren ( l_expr_id ) := h_exprid_numberofchildren ( l_expr_id ) + 1;
6628 
6629             generate_expression ( t_lhs_index ( i ), l_input_context, x_output_context );
6630 
6631         END LOOP;
6632 
6633         invoke_anyalltrue ( t_exp_templateid ( t_lhs_operator ( 1 )), h_exprid_numberofchildren ( l_expr_id ));
6634 
6635         l_exprnode_id := t_exp_exprnodeid ( t_rhs_operator ( 1 ));
6636         l_expr_id := TO_CHAR ( l_exprnode_id );
6637 
6638         h_exprid_numberofchildren ( l_expr_id ) := 0;
6639 
6640         FOR i IN 1..t_rhs_index.COUNT LOOP
6641 
6642             t_exp_exprparentid ( t_rhs_index ( i )) := l_exprnode_id;
6643             h_exprid_numberofchildren ( l_expr_id ) := h_exprid_numberofchildren ( l_expr_id ) + 1;
6644 
6645             generate_expression ( t_rhs_index ( i ), l_input_context, x_output_context );
6646 
6647         END LOOP;
6648 
6649         invoke_anyalltrue ( t_exp_templateid ( t_rhs_operator ( 1 )), h_exprid_numberofchildren ( l_expr_id ));
6650         emit_invokevirtual ( h_operators_2 ( t_logic_operator ( 1 )));
6651 
6652      END generate_logic_template;
6653      ----------------------------------------------------------------------------------
6654      -- Scope: compile_constraints
6655      PROCEDURE generate_comparison_template ( j IN PLS_INTEGER
6656                                             , p_input_context IN expression_context
6657                                             , x_output_context IN OUT NOCOPY expression_context
6658                                             ) IS
6659 
6660         l_expr_id               VARCHAR2(4000);
6661         l_exprnode_id           NUMBER;
6662         l_index                 PLS_INTEGER;
6663         l_expr_index            PLS_INTEGER;
6664 
6665         t_lhs_operand           type_integer_table;
6666         t_comparison_operator   type_integer_table;
6667         t_rhs_operand           type_integer_table;
6668         t_logic_operator        type_integer_table;
6669         t_rhs_operator          type_integer_table;
6670         t_rhs_index             type_integer_table;
6671 
6672         l_input_context         expression_context;
6673 
6674      BEGIN
6675 
6676         --This procedure implements generation of simple comparison rule. The template application
6677         --specifies the following parameters:
6678 
6679         -- param_index = 1: left operand of the comparison operator
6680         -- param_index = 2: comparison operator
6681         -- param_index = 3: right operand of the comparison operator
6682         -- param_index = 4: logic operator
6683         -- param_index = 5: right-hand side AnyTrue or AllTrue operator
6684         -- param_index = 6: right-hand side participant(s)
6685 
6686         l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
6687 
6688         IF ( expr_has_children( l_expr_id )) THEN
6689 
6690           l_index := h_exprid_childrenindex ( l_expr_id ) - 1;
6691 
6692         ELSE
6693 
6694           report_and_raise_rule_sys_warn (
6695                 p_text => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SW_RE_ENODE_CHILDREN,
6696                             'EXPR_ID', l_expr_id ),
6697                 p_warning_location => 'generate_comparison_template');
6698 
6699         END IF;
6700 
6701         --Parse the template application.
6702 
6703         FOR i IN 1..h_exprid_numberofchildren ( l_expr_id ) LOOP
6704 
6705            l_expr_index := l_index + i;
6706 
6707            CASE t_exp_paramindex ( l_expr_index )
6708 
6709                WHEN 1 THEN
6710 
6711                   t_lhs_operand ( t_lhs_operand.COUNT + 1 ) := l_expr_index;
6712 
6713                WHEN 2 THEN
6714 
6715                   t_comparison_operator ( t_comparison_operator.COUNT + 1 ) := t_exp_templateid ( l_expr_index );
6716 
6717                WHEN 3 THEN
6718 
6719                   t_rhs_operand ( t_rhs_operand.COUNT + 1 ) := l_expr_index;
6720 
6721                WHEN 4 THEN
6722 
6723                   t_logic_operator ( t_logic_operator.COUNT + 1 ) := t_exp_templateid ( l_expr_index );
6724 
6725                WHEN 5 THEN
6726 
6727                   t_rhs_operator ( t_rhs_operator.COUNT + 1 ) := l_expr_index;
6728 
6729                WHEN 6 THEN
6730 
6731                   t_rhs_index ( t_rhs_index.COUNT + 1 ) := l_expr_index;
6732 
6733            END CASE;
6734         END LOOP;
6735 
6736         --Verify the template application.
6737 
6738         IF ( t_lhs_operand.COUNT <> 1 ) THEN
6739 
6740             report_and_raise_rule_sys_warn(
6741                 p_text => GET_NOT_TRANSLATED_TEXT(
6742                         CZ_FCE_SW_CR_NO_LHS_OPAND ),
6743                 p_warning_location => 'generate_comparison_template');
6744 
6745         ELSIF ( t_comparison_operator.COUNT <> 1 OR ( NOT h_operators_2.EXISTS ( t_comparison_operator ( 1 )))) THEN
6746 
6747             report_and_raise_rule_sys_warn(
6748                 p_text => GET_NOT_TRANSLATED_TEXT(
6749                         CZ_FCE_SW_CR_NO_OPERATOR ),
6750                 p_warning_location => 'generate_comparison_template');
6751 
6752         ELSIF ( t_rhs_operand.COUNT <> 1 ) THEN
6753 
6754             report_and_raise_rule_sys_warn(
6755                 p_text => GET_NOT_TRANSLATED_TEXT(
6756                         CZ_FCE_SW_CR_NO_RHS_OPAND ),
6757                 p_warning_location => 'generate_comparison_template');
6758 
6759         ELSIF ( t_logic_operator.COUNT <> 1 OR ( NOT h_operators_2.EXISTS ( t_logic_operator ( 1 )))) THEN
6760 
6761             report_and_raise_rule_sys_warn(
6762                 p_text => GET_NOT_TRANSLATED_TEXT(
6763                         CZ_FCE_SW_CR_NO_LOGIC_OP ),
6764                 p_warning_location => 'generate_comparison_template');
6765 
6766         ELSIF ( t_rhs_operator.COUNT <> 1 OR ( NOT h_operators_3.EXISTS ( t_exp_templateid ( t_rhs_operator ( 1 ))))) THEN
6767 
6768             report_and_raise_rule_sys_warn(
6769                 p_text => GET_NOT_TRANSLATED_TEXT(
6770                         CZ_FCE_SW_CR_NO_RHS_OP ),
6771                 p_warning_location => 'generate_comparison_template');
6772 
6773         ELSIF ( t_rhs_index.COUNT = 0 ) THEN
6774             -- Right-hand side participants are missing.  Comparison rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
6775             report_and_raise_rule_warning(
6776                 p_text => CZ_UTILS.GET_TEXT(
6777                         CZ_FCE_W_CR_MISSING_RHS_PARTS,
6778                         'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
6779                         'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
6780                 p_warning_location => 'generate_comparison_template');
6781 
6782         END IF;
6783 
6784         --Generate the math expression which is left-hand side of the logic operator.
6785 
6786         l_input_context.context_type := const_context_numeric;
6787 
6788         generate_expression ( t_lhs_operand ( 1 ), l_input_context, x_output_context );
6789         generate_expression ( t_rhs_operand ( 1 ), l_input_context, x_output_context );
6790 
6791         invoke_operator2 ( t_comparison_operator ( 1 ), t_rhs_operand ( 1 ), x_output_context );
6792 
6793         l_input_context.context_type := const_context_logical;
6794 
6795         --Need to emulate all participants as children of the AnyTrue or AllTrue operator
6796         --in order to provide context for participants' generation, and to know the exact
6797         --number of arguments to this operator.
6798 
6799         l_exprnode_id := t_exp_exprnodeid ( t_rhs_operator ( 1 ));
6800         l_expr_id := TO_CHAR ( l_exprnode_id );
6801 
6802         h_exprid_numberofchildren ( l_expr_id ) := 0;
6803 
6804         FOR i IN 1..t_rhs_index.COUNT LOOP
6805 
6806             t_exp_exprparentid ( t_rhs_index ( i )) := l_exprnode_id;
6807             h_exprid_numberofchildren ( l_expr_id ) := h_exprid_numberofchildren ( l_expr_id ) + 1;
6808 
6809             generate_expression ( t_rhs_index ( i ), l_input_context, x_output_context );
6810 
6811         END LOOP;
6812 
6813         invoke_anyalltrue ( t_exp_templateid ( t_rhs_operator ( 1 )), h_exprid_numberofchildren ( l_expr_id ));
6814         emit_invokevirtual ( h_operators_2 ( t_logic_operator ( 1 )));
6815 
6816      END generate_comparison_template;
6817      ----------------------------------------------------------------------------------
6818      FUNCTION next_interval_key ( p_target_id IN PLS_INTEGER ) RETURN VARCHAR2 IS
6819 
6820        l_seq   PLS_INTEGER := t_acc_target_sequence ( p_target_id );
6821 
6822      BEGIN
6823 
6824         t_acc_target_sequence ( p_target_id ) := l_seq + 1;
6825         RETURN TO_CHAR ( l_seq ) || '$' || t_acc_targets ( p_target_id );
6826 
6827      END next_interval_key;
6828      ----------------------------------------------------------------------------------
6829      --This function adds instance quantifies, generated for the new contribution, to the
6830      --list of instance quantifiers of the record with index p_index.
6831 
6832      PROCEDURE combine_instance_quantifiers ( p_target_id IN PLS_INTEGER, p_index IN PLS_INTEGER ) IS
6833 
6834         l_count   PLS_INTEGER;
6835 
6836      BEGIN
6837 
6838         --Add all the quantifiers that were created for this contribution and are not present in the
6839         --record's arrays, to the record.
6840 
6841         FOR i IN 1..t_acc_local_quantifiers.COUNT LOOP
6842 
6843            IF ( NOT t_acc_contributors ( p_target_id )( p_index ).hash_quantifiers.EXISTS ( t_acc_local_quantifiers ( i ))) THEN
6844 
6845               l_count := t_acc_contributors ( p_target_id )( p_index ).quantifiers.COUNT + 1;
6846 
6847               t_acc_contributors ( p_target_id )( p_index ).quantifiers ( l_count ) := t_acc_local_quantifiers ( i );
6848               t_acc_contributors ( p_target_id )( p_index ).hash_quantifiers ( t_acc_local_quantifiers ( i )) := 1;
6849 
6850            END IF;
6851         END LOOP;
6852      END combine_instance_quantifiers;
6853      ----------------------------------------------------------------------------------
6854      --This function is used to store a combined contribution for the newly created record
6855      --with index p_index. When this function is called, the new contribution is on top of
6856      --stack.
6857 
6858      --The function combines the new contribution with the contribution which is currently
6859      --stored in the register p_exist_key (if any) and stores the combined contribution in
6860      --the register of the new record (the value is removed from stack). Target's instance
6861      --quantifiers are combined.
6862 
6863      PROCEDURE combine_contributions ( p_target_id IN PLS_INTEGER, p_index IN PLS_INTEGER, p_exist_key IN VARCHAR2 ) IS
6864      BEGIN
6865 
6866         aload_register ('value');
6867 
6868         IF ( p_exist_key IS NOT NULL ) THEN
6869 
6870            aload_register ( p_exist_key );
6871            emit_invokevirtual ('INumExprDef.sum(INumExprDef)');
6872 
6873         END IF;
6874 
6875         IF ( t_acc_contributors ( p_target_id )( p_index ).interval_key IS NULL ) THEN
6876 
6877            t_acc_contributors ( p_target_id )( p_index ).interval_key := next_interval_key ( p_target_id );
6878 
6879         END IF;
6880 
6881         astore_register ( t_acc_contributors ( p_target_id )( p_index ).interval_key );
6882         combine_instance_quantifiers ( p_target_id, p_index );
6883 
6884      END combine_contributions;
6885      ----------------------------------------------------------------------------------
6886      PROCEDURE combine_contribution_records ( p_target_id IN PLS_INTEGER, p_index IN PLS_INTEGER, p_exist_key IN VARCHAR2 ) IS
6887 
6888         l_count         PLS_INTEGER;
6889 
6890         l_exist_mask_   RAW(16);
6891         l_new_mask_     RAW(16);
6892 
6893         l_common_mask   VARCHAR2(16);
6894         l_exist_mask    VARCHAR2(16);
6895         l_new_mask      VARCHAR2(16);
6896 
6897      BEGIN
6898 
6899         l_exist_mask_ := HEXTORAW ( t_acc_contributors ( p_target_id )( p_index ).effective_usage_mask );
6900         l_new_mask_ := HEXTORAW ( this_effective_usages );
6901 
6902         l_common_mask := RAWTOHEX ( UTL_RAW.BIT_OR ( l_exist_mask_, l_new_mask_ ));
6903 
6904         IF ( l_common_mask <> const_mask_no_usages ) THEN
6905 
6906            --Usages, defined only for the existing contribution record.
6907 
6908            l_exist_mask := RAWTOHEX ( UTL_RAW.BIT_OR ( l_exist_mask_, UTL_RAW.BIT_COMPLEMENT ( l_new_mask_ )));
6909 
6910            --Usages, defined only for the new contribution.
6911 
6912            l_new_mask := RAWTOHEX ( UTL_RAW.BIT_OR ( UTL_RAW.BIT_COMPLEMENT ( l_exist_mask_ ), l_new_mask_ ));
6913 
6914            IF ( l_common_mask = t_acc_contributors ( p_target_id )( p_index ).effective_usage_mask ) THEN
6915 
6916               --New usage mask containt the existing or masks are equal, combine contributions on the existing
6917               --record.
6918 
6919               IF ( t_acc_contributors ( p_target_id )( p_index ).interval_key IS NOT NULL ) THEN
6920 
6921                  --If the interval has a contribution stored in a register, we need to create a new register
6922                  --because we will be changing the contribution while the existing register may be also used
6923                  --on some other interval.
6924 
6925                  t_acc_contributors ( p_target_id )( p_index ).interval_key := next_interval_key ( p_target_id );
6926 
6927               END IF;
6928 
6929               combine_contributions ( p_target_id, p_index, p_exist_key );
6930 
6931            ELSE
6932 
6933               --Existing usage mask contains the new or masks intersect. We need to change the mask
6934               --on the existing record to l_exist_mask because only on this usages we will have the
6935               --existing contribution. Then we create a new record for common usages summing up the
6936               --contributions.
6937 
6938               l_count := t_acc_contributors ( p_target_id ).COUNT + 1;
6939               t_acc_contributors ( p_target_id )( l_count ) := t_acc_contributors ( p_target_id )( p_index );
6940 
6941               t_acc_contributors ( p_target_id )( p_index ).effective_usage_mask := l_exist_mask;
6942 
6943               t_acc_contributors ( p_target_id )( l_count ).effective_usage_mask := l_common_mask;
6944               t_acc_contributors ( p_target_id )( l_count ).interval_key := next_interval_key ( p_target_id );
6945 
6946               combine_contributions ( p_target_id, l_count, p_exist_key );
6947 
6948            END IF;
6949         END IF;
6950      END combine_contribution_records;
6951      ----------------------------------------------------------------------------------
6952      PROCEDURE combine_contributors ( p_target_id IN PLS_INTEGER ) IS
6953 
6954         l_contribs      PLS_INTEGER;
6955         l_count         PLS_INTEGER;
6956 
6957         l_eff_from      DATE;
6958         l_eff_until     DATE;
6959 
6960      BEGIN
6961 
6962         IF ( t_acc_contributors.EXISTS ( p_target_id )) THEN
6963 
6964            --There are existing contributions to this target. We need combine this new contribution
6965            --with others according to effectivities and usages.
6966 
6967            --The new contribution is currently on top of the stack and needs to be available for
6968            --each interval that we process. We store it in a dedicated register and then push it
6969            --from there before each use.
6970 
6971            astore_register ('value');
6972            l_contribs := t_acc_contributors ( p_target_id ).COUNT;
6973 
6974            FOR i IN 1..l_contribs LOOP
6975 
6976               l_eff_from := t_acc_contributors ( p_target_id )( i ).effective_from;
6977               l_eff_until := t_acc_contributors ( p_target_id )( i ).effective_until;
6978 
6979               IF ( this_effective_until > l_eff_from AND this_effective_from < l_eff_until ) THEN
6980 
6981                  --Effectivity intervals intersect.
6982 
6983                  IF ( this_effective_from <= l_eff_from AND this_effective_until >= l_eff_until ) THEN
6984 
6985                     --        |------------------------| - existing interval
6986                     -- |------------------------------------| - new interval
6987 
6988                     --The new contribution's effectivity interval contains the existing interval, or intervals
6989                     --are the same, including the case when both are always effective.
6990 
6991                     combine_contribution_records ( p_target_id, i, t_acc_contributors ( p_target_id )( i ).interval_key );
6992 
6993                  ELSE
6994 
6995                     --One or both ends of the new effectivity interval are inside the existing interval, split them
6996                     --into several intervals and add them to the table of contribution records.
6997 
6998                     l_count := t_acc_contributors ( p_target_id ).COUNT + 1;
6999                     t_acc_contributors ( p_target_id )( l_count ) := t_acc_contributors ( p_target_id )( i );
7000 
7001                     IF ( this_effective_from <= l_eff_from ) THEN
7002 
7003                        --        |------------------------| - existing interval
7004                        -- |----------------| - new interval
7005 
7006                        --Modify the existing interval. As contributions does not change, we don't need to store it
7007                        --in the register, it's already there.
7008 
7009                        t_acc_contributors ( p_target_id )( i ).effective_from := this_effective_until;
7010 
7011                        --Create a new record for the intersection.
7012 
7013                        t_acc_contributors ( p_target_id )( l_count ).effective_from := l_eff_from;
7014                        t_acc_contributors ( p_target_id )( l_count ).effective_until := this_effective_until;
7015 
7016                     ELSIF ( this_effective_until >= l_eff_until ) THEN
7017 
7018                        -- |------------------------| - existing interval
7019                        --               |-----------------| - new interval
7020 
7021                        --Modify the existing interval. As contributions does not change, we don't need to store it
7022                        --in the register, it's already there.
7023 
7024                        t_acc_contributors ( p_target_id )( i ).effective_until := this_effective_from;
7025 
7026                        --Create a new record for the intersection.
7027 
7028                        t_acc_contributors ( p_target_id )( l_count ).effective_from := this_effective_from;
7029                        t_acc_contributors ( p_target_id )( l_count ).effective_until := l_eff_until;
7030 
7031                     ELSE
7032 
7033                        -- |------------------------| - existing interval
7034                        --     |------------| - new interval
7035 
7036                        --Split the existing interval into two with the same contributions.
7037 
7038                        t_acc_contributors ( p_target_id )( i ).effective_until := this_effective_from;
7039                        t_acc_contributors ( p_target_id )( l_count ).effective_from := this_effective_until;
7040 
7041                        --Create a new record for the intersection.
7042 
7043                        l_count := l_count + 1;
7044                        t_acc_contributors ( p_target_id )( l_count ) := t_acc_contributors ( p_target_id )( i );
7045 
7046                        t_acc_contributors ( p_target_id )( l_count ).effective_from := this_effective_from;
7047                        t_acc_contributors ( p_target_id )( l_count ).effective_until := this_effective_until;
7048 
7049                     END IF;
7050 
7051                     --Process the intersection for usages.
7052 
7053                     combine_contribution_records ( p_target_id, l_count, t_acc_contributors ( p_target_id )( i ).interval_key );
7054 
7055                  END IF;
7056               END IF;
7057            END LOOP;
7058 
7059         ELSE
7060 
7061            --This is the first contributor to this target.
7062 
7063            l_count := 1;
7064 
7065            IF ( this_effective_from > const_epoch_begin ) THEN
7066 
7067               t_acc_contributors ( p_target_id )( l_count ).effective_from := const_epoch_begin;
7068               t_acc_contributors ( p_target_id )( l_count ).effective_until := this_effective_from;
7069               t_acc_contributors ( p_target_id )( l_count ).effective_usage_mask := const_mask_all_usages;
7070 
7071               t_acc_contributors ( p_target_id )( l_count ).interval_key := NULL;
7072               t_acc_contributors ( p_target_id )( l_count ).quantifiers := t_acc_quantifiers ( p_target_id );
7073               t_acc_contributors ( p_target_id )( l_count ).hash_quantifiers := h_acc_quantifiers ( p_target_id );
7074 
7075               l_count := l_count + 1;
7076 
7077            END IF;
7078 
7079            t_acc_contributors ( p_target_id )( l_count ).interval_key := next_interval_key ( p_target_id );
7080 
7081            --Note that t_acc_quantifiers at this point contains also the target's quantifier, so
7082            --we are initializing the quantifiers array with all quantifiers generated for the
7083            --first contribution to this target. After that we will be appending this array, when
7084            --combining contributions, with quantifiers, generated for contributors.
7085 
7086            t_acc_contributors ( p_target_id )( l_count ).effective_from := this_effective_from;
7087            t_acc_contributors ( p_target_id )( l_count ).effective_until := this_effective_until;
7088            t_acc_contributors ( p_target_id )( l_count ).effective_usage_mask := this_effective_usages;
7089 
7090            t_acc_contributors ( p_target_id )( l_count ).quantifiers := t_acc_quantifiers ( p_target_id );
7091            t_acc_contributors ( p_target_id )( l_count ).hash_quantifiers := h_acc_quantifiers ( p_target_id );
7092 
7093            astore_register ( t_acc_contributors ( p_target_id )( l_count ).interval_key );
7094 
7095            IF ( this_effective_usages <> const_mask_all_usages ) THEN
7096 
7097               --If this contribution is not for all usages, we need to add a dummy record with null
7098               --key and complemental usage mask. It works for the same purpose as dummy effectivity
7099               --intervals.
7100 
7101               l_count := l_count + 1;
7102 
7103               t_acc_contributors ( p_target_id )( l_count ).effective_from := this_effective_from;
7104               t_acc_contributors ( p_target_id )( l_count ).effective_until := this_effective_until;
7105               t_acc_contributors ( p_target_id )( l_count ).effective_usage_mask := RAWTOHEX ( UTL_RAW.BIT_COMPLEMENT ( this_effective_usages ));
7106 
7107               t_acc_contributors ( p_target_id )( l_count ).interval_key := NULL;
7108               t_acc_contributors ( p_target_id )( l_count ).quantifiers := t_acc_quantifiers ( p_target_id );
7109               t_acc_contributors ( p_target_id )( l_count ).hash_quantifiers := h_acc_quantifiers ( p_target_id );
7110 
7111            END IF;
7112 
7113            IF ( this_effective_until < const_epoch_end ) THEN
7114 
7115               l_count := l_count + 1;
7116 
7117               t_acc_contributors ( p_target_id )( l_count ).effective_from := this_effective_until;
7118               t_acc_contributors ( p_target_id )( l_count ).effective_until := const_epoch_end;
7119               t_acc_contributors ( p_target_id )( l_count ).effective_usage_mask := const_mask_all_usages;
7120 
7121               t_acc_contributors ( p_target_id )( l_count ).interval_key := NULL;
7122               t_acc_contributors ( p_target_id )( l_count ).quantifiers := t_acc_quantifiers ( p_target_id );
7123               t_acc_contributors ( p_target_id )( l_count ).hash_quantifiers := h_acc_quantifiers ( p_target_id );
7124 
7125            END IF;
7126         END IF;
7127      END combine_contributors;
7128      ----------------------------------------------------------------------------------
7129      -- Scope: compile_constraints
7130      PROCEDURE generate_accumulator_template ( j IN PLS_INTEGER
7131                                              , p_input_context IN expression_context
7132                                              , x_output_context IN OUT NOCOPY expression_context
7133                                              ) IS
7134 
7135         l_expr_id             VARCHAR2(4000);
7136         l_index               PLS_INTEGER;
7137         l_expr_index          PLS_INTEGER;
7138         l_count               PLS_INTEGER;
7139         l_key                 VARCHAR2(4000);
7140 
7141         t_contributor_index   type_integer_table;
7142         t_multiplier          type_number_table;
7143         t_accumulation_op     type_integer_table;
7144         t_rounding_op         type_integer_table;
7145         t_target_index        type_integer_table;
7146 
7147         l_input_context       expression_context;
7148 
7149      BEGIN
7150 
7151         --This procedure implements generation of simple accumulation rule. The template application
7152         --specifies the following parameters:
7153 
7154         -- param_index = 1: contributor(s)
7155         -- param_index = 2: multiplier (constant)
7156         -- param_index = 3: accumulation operator
7157         -- param_index = 4: rounding operator
7158         -- param_index = 5: target
7159 
7160         l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
7161 
7162         IF ( expr_has_children ( l_expr_id )) THEN
7163 
7164           l_index := h_exprid_childrenindex ( l_expr_id ) - 1;
7165 
7166         ELSE
7167 
7168           report_and_raise_rule_sys_warn (
7169                 p_text => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SW_RE_ENODE_CHILDREN,
7170                             'EXPR_ID', l_expr_id ),
7171                 p_warning_location => 'generate_accumulator_template');
7172 
7173         END IF;
7174 
7175         --Parse the template application.
7176 
7177         FOR i IN 1..h_exprid_numberofchildren ( l_expr_id ) LOOP
7178 
7179            l_expr_index := l_index + i;
7180 
7181            CASE t_exp_paramindex ( l_expr_index )
7182 
7183                WHEN 1 THEN
7184 
7185                   t_contributor_index ( t_contributor_index.COUNT + 1 ) := l_expr_index;
7186 
7187                WHEN 2 THEN
7188 
7189                   t_multiplier ( t_multiplier.COUNT + 1 ) := NVL ( t_exp_datanumvalue ( l_expr_index ), 1 );
7190 
7191                WHEN 3 THEN
7192 
7193                   t_accumulation_op ( t_accumulation_op.COUNT + 1 ) := t_exp_templateid ( l_expr_index );
7194 
7195                WHEN 4 THEN
7196 
7197                   t_rounding_op ( t_rounding_op.COUNT + 1 ) := t_exp_templateid ( l_expr_index );
7198 
7199                WHEN 5 THEN
7200 
7201                   t_target_index ( t_target_index.COUNT + 1 ) := l_expr_index;
7202 
7203            END CASE;
7204         END LOOP;
7205 
7206         --Verify the template application.
7207 
7208         IF ( t_contributor_index.COUNT = 0 ) THEN
7209 
7210             report_and_raise_rule_sys_warn(
7211                 p_text => GET_NOT_TRANSLATED_TEXT(
7212                         CZ_FCE_SW_AR_NO_LHS_OPAND ),
7213                 p_warning_location => 'generate_accumulator_template');
7214 
7215         ELSIF ( t_multiplier.COUNT <> 1 ) THEN
7216 
7217             report_and_raise_rule_sys_warn(
7218                 p_text => GET_NOT_TRANSLATED_TEXT(
7219                         CZ_FCE_SW_AR_NO_MLTIPLIER ),
7220                 p_warning_location => 'generate_accumulator_template');
7221 
7222         ELSIF ( t_accumulation_op.COUNT <> 1 OR ( NOT h_accumulation_ops.EXISTS ( t_accumulation_op ( 1 )))) THEN
7223 
7224             report_and_raise_rule_sys_warn(
7225                 p_text => GET_NOT_TRANSLATED_TEXT(
7226                         CZ_FCE_SW_AR_NO_OPERATOR ),
7227                 p_warning_location => 'generate_accumulator_template');
7228 
7229         ELSIF ( t_rounding_op.COUNT <> 1 OR ( NOT h_rounding_ops.EXISTS ( t_rounding_op ( 1 )))) THEN
7230 
7231             report_and_raise_rule_sys_warn(
7232                 p_text => GET_NOT_TRANSLATED_TEXT(
7233                         CZ_FCE_SW_AR_NO_ROUND_OP ),
7234                 p_warning_location => 'generate_accumulator_template');
7235 
7236         ELSIF ( t_target_index.COUNT <> 1 ) THEN
7237 
7238             report_and_raise_rule_sys_warn(
7239                 p_text => GET_NOT_TRANSLATED_TEXT(
7240                         CZ_FCE_SW_AR_NO_RHS_OPAND ),
7241                 p_warning_location => 'generate_accumulator_template');
7242 
7243         END IF;
7244 
7245         --Need to generate the target first, because generation of contributor will depend on the
7246         --target (LCA). Cannot just generate the path here because target can be an argument, for
7247         --example, in case of FORALL operator.
7248 
7249         l_input_context.context_type := const_context_target;
7250         generate_expression ( t_target_index ( 1 ), l_input_context, x_output_context );
7251 
7252         l_count := x_output_context.context_num_data;
7253         l_key := x_output_context.context_data;
7254 
7255         --If output context is 'target', the target didn't exist and needs to be stored.
7256         --For an exiting target, the context would have been changed to 'generic' in
7257         --generate_path procedure.
7258 
7259         IF ( x_output_context.context_type = const_context_target ) THEN
7260 
7261            astore_register ( l_key );
7262 
7263            t_target_quantifiers ( l_count ) := t_acc_quantifiers ( l_count );
7264            h_target_quantifiers ( l_count ) := h_acc_quantifiers ( l_count );
7265 
7266         END IF;
7267 
7268         --If there are more than 2 contributors, we will put them into an array and call
7269         --IModelDef.sum. To do this, we need extra model def on stack.
7270 
7271         IF ( t_contributor_index.COUNT > 2 ) THEN
7272 
7273             aload_model_def ( p_component_id );
7274 
7275         END IF;
7276 
7277         --Now generate all the contributors.
7278 
7279         t_acc_local_quantifiers.DELETE;
7280 
7281         FOR i IN 1..t_contributor_index.COUNT LOOP
7282 
7283             l_input_context.context_type := const_context_contributor;
7284             l_input_context.context_num_data := l_count;
7285 
7286             generate_expression ( t_contributor_index ( i ), l_input_context, x_output_context );
7287 
7288             --Multiply by the multiplier if it is other than 1.
7289 
7290             IF ( t_multiplier ( 1 ) <> 1 ) THEN
7291 
7292                emit_invokevirtual ( CASE push_numeric_literal ( t_multiplier ( 1 ))
7293                                     WHEN h_datatypes ('integer') THEN 'INumExprDef.prod(int)'
7294                                     ELSE 'INumExprDef.prod(double)'
7295                                     END );
7296             END IF;
7297 
7298             --Apply the rounding operator if any.
7299 
7300             IF ( t_rounding_op ( 1 ) <> h_templates ('none')) THEN
7301 
7302                emit_invokevirtual ( h_operators_1 ( t_rounding_op ( 1 )));
7303 
7304             END IF;
7305         END LOOP;
7306 
7307         --Sum up all the generated contributors as appropriate.
7308 
7309         IF ( t_contributor_index.COUNT = 2 ) THEN
7310 
7311            emit_invokevirtual ('INumExprDef.sum(INumExprDef)');
7312 
7313         ELSIF ( t_contributor_index.COUNT > 2 ) THEN
7314 
7315            create_array ( t_contributor_index.COUNT, h_javatypes ('INumExprDef'));
7316            populate_array ( t_contributor_index.COUNT );
7317            emit_invokevirtual ('IModelDef.sum(INumExprDef[])');
7318 
7319         END IF;
7320 
7321         IF ( t_accumulation_op ( 1 ) = h_templates ('subtractsfrom')) THEN
7322 
7323            emit_invokevirtual ('INumExprDef.neg()');
7324 
7325         END IF;
7326 
7327         combine_contributors ( l_count );
7328         x_output_context.context_type := const_context_accumulation;
7329 
7330      END generate_accumulator_template;
7331      ----------------------------------------------------------------------------------
7332      -- Scope: compile_constraints
7333      PROCEDURE generate_compat_table ( p_compat_table   type_compat_table
7334                                      , p_input_context  IN expression_context
7335                                      , x_output_context IN OUT NOCOPY expression_context
7336                                      ) IS
7337 
7338         l_key               VARCHAR2(4000);
7339         l_exclude_key       VARCHAR2(4000);
7340         l_node_id           VARCHAR2(4000);
7341         l_expl_id           VARCHAR2(4000);
7342         l_option_id         NUMBER;
7343 
7344         l_participants      PLS_INTEGER;
7345         l_combinations      PLS_INTEGER;
7346         l_return            PLS_INTEGER;
7347         l_index             PLS_INTEGER;
7348         l_count             PLS_INTEGER;
7349 
7350         tl_sizes            type_integer_table;
7351         tl_excludes_id      type_number_table;
7352         tl_excludes         type_varchar4000_table;
7353         hl_options          type_datahashtable_table;
7354 
7355      BEGIN
7356 
7357         h_instancequantifiers.DELETE;
7358         t_instancequantifiers.DELETE;
7359 
7360         l_combinations := p_compat_table.combinations.COUNT;
7361         l_participants := p_compat_table.participants.COUNT;
7362 
7363         --This is to call IModelDef.addConstraint
7364 
7365         aload_model_def ( p_component_id );
7366 
7367         --This is to call IModelDef.compat. As model def is definitely in a local variable after
7368         --the previous call, this may be faster than dup.
7369 
7370         IF ( l_combinations > 0 ) THEN
7371 
7372             --We will need to call compat only if there are combinations.
7373 
7374             aload_model_def ( p_component_id );
7375 
7376         END IF;
7377 
7378         --Generate all the participants.
7379 
7380         FOR i IN 1..l_participants LOOP
7381 
7382            IF ( h_psnid_detailedtype ( p_compat_table.participants ( i ).ps_node_id ) NOT IN
7383                    ( h_psntypes ('optionfeature'), h_psntypes ('bomoptionclass'))) THEN
7384             -- Invalid participant in compatibility rule.  Valid participants are Option Feature or BOM Option Class nodes.  Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
7385             report_and_raise_rule_warning(
7386                 p_text => CZ_UTILS.GET_TEXT(
7387                         CZ_FCE_W_CMR_INVALID_PART,
7388                         'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
7389                         'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
7390                 p_warning_location => 'generate_compat_table');
7391 
7392            END IF;
7393 
7394            l_return := generate_path ( p_compat_table.participants ( i ).ps_node_id
7395                                      , p_compat_table.participants ( i ).model_ref_expl_id
7396                                      , p_input_context
7397                                      , x_output_context );
7398 
7399            IF ( l_return = const_quantifier_created ) THEN
7400 
7401               emit_invokevirtual('IInstanceQuantifier.getExprFromInstance(IExprDef)');
7402 
7403            END IF;
7404 
7405            --We will not need to store in a local variable if there is no excludes for this feature,
7406            --or if there are no combinations, so this can be optimized.
7407 
7408            l_key := TO_CHAR ( p_compat_table.participants ( i ).ps_node_id ) || '-' ||
7409                     TO_CHAR ( p_compat_table.participants ( i ).model_ref_expl_id );
7410 
7411            IF ( l_combinations > 0 ) THEN
7412 
7413               IF ( NOT local_variable_defined ( l_key )) THEN
7414 
7415                   copyto_local_variable ( l_key );
7416 
7417               END IF;
7418 
7419            ELSE
7420 
7421               --If there is no combinations, we will be generating an exclude, and do not need to
7422               --store the participants, instead, we need to apply the logical context.
7423 
7424               apply_context ( p_compat_table.participants ( i ).ps_node_id, l_return, const_context_logical );
7425 
7426            END IF;
7427         END LOOP;
7428 
7429         IF ( l_combinations = 0 ) THEN
7430 
7431            --There is no combinations. This is possible between a primary and an optional feature.
7432            --Generate exclude and return.
7433 
7434            --#<optimization>As an optimization, we could collect all optional features with no selections
7435            --before we go into generate_compat_table. There is no need to build compatibility tables for
7436            --such features and process them separately, we could just exclude all of them. This could be
7437            --implemented, but it's not a good idea to use Design Chart for such purposes anyway.
7438 
7439            emit_invokevirtual ('ILogicExprDef.excludes(ILogicExprDef)');
7440            set_reason_id ();
7441            add_constraint ();
7442 
7443            RETURN;
7444         END IF;
7445 
7446         --Create the array of participants that will be the first argument to compat.
7447 
7448         create_array ( l_participants, h_javatypes ('Object'));
7449         populate_array ( l_participants );
7450 
7451         --Now we need to create the second argument for the compat - a two-dimensional array of all combinations.
7452         --For non-bom, the second dimension is the array of the names of options comprising the combination. For
7453         --bom the type depends on the bom type. Mixed case is also possible.
7454 
7455         --Create an array for each combination. Note, that the correct order of options within the combinations
7456         --is guaranteed by the construction of p_compat_table.combinations
7457 
7458         FOR i IN 1..l_combinations LOOP
7459             FOR j IN 1..l_participants LOOP
7460 
7461                l_key := TO_CHAR ( p_compat_table.participants ( j ).ps_node_id ) || '-' ||
7462                         TO_CHAR ( p_compat_table.participants ( j ).model_ref_expl_id );
7463 
7464                l_option_id := p_compat_table.combinations ( i )( j ).ps_node_id;
7465                l_index := h_psnid_backindex ( l_option_id );
7466 
7467                IF ( t_psn_psnodetype ( l_index ) = h_psntypes ('option')) THEN
7468 
7469                   push_variable_name ( l_option_id );
7470 
7471                ELSE
7472 
7473                   --The parent is bom. The following approach should work for all kinds of options
7474                   --including references.
7475 
7476                   IF ( h_psnid_devlprojectid ( l_option_id ) = p_component_id ) THEN
7477 
7478                      haload_object ( l_option_id , 1 );
7479 
7480                   ELSE
7481 
7482                      --push_variable assumes that the parent is on the stack if the variable is remote.
7483                      --Note that we need the participant in the local context and we won't be calling
7484                      --getVarRef on it therefore we don't neef to dup the parent as push_variable does.
7485 
7486                      aload_context_node ( l_key, const_context_generic );
7487 
7488                      emit_invokevirtual ( 'ISingletonExprDef.getType()');
7489                      push_variable_name ( l_option_id );
7490                      emit_invokevirtual ( 'IModelDef.getVar(String)');
7491 
7492                   END IF;
7493                END IF;
7494 
7495                --Mark that this option participates in a combination.
7496 
7497                hl_options ( j )( TO_CHAR ( l_option_id )) := 1;
7498 
7499             END LOOP;
7500 
7501             create_array ( l_participants, h_javatypes ('Object'));
7502             populate_array ( l_participants );
7503 
7504         END LOOP;
7505 
7506         --Create two-dimensional array and populate the first dimension.
7507 
7508         tl_sizes ( 1 ) := l_combinations;
7509         tl_sizes ( 2 ) := l_participants;
7510 
7511         create_multi_array ( tl_sizes, h_javatypes ('Object'));
7512         populate_array ( l_combinations );
7513 
7514         --Finally call the compat to generate the constraint.
7515 
7516         emit_invokevirtual ('IModelDef.compat(Object[], Object[][])');
7517 
7518         set_reason_id ();
7519         add_constraint ();
7520 
7521         --Now we need to generate all the exclude constraints for the options that don't
7522         --participate in compat.
7523 
7524         FOR i IN 1..l_participants LOOP
7525 
7526            --Collect all the options that are not in the combinations.
7527 
7528            l_node_id := TO_CHAR ( p_compat_table.participants ( i ).ps_node_id );
7529            l_expl_id := TO_CHAR ( p_compat_table.participants ( i ).model_ref_expl_id );
7530 
7531            l_key := l_node_id || '-' || l_expl_id;
7532 
7533            l_index := h_psnid_backindex ( l_node_id );
7534 
7535            IF ( h_psnid_numberofchildren ( l_node_id ) <> hl_options ( i ).COUNT ) THEN
7536 
7537               --Number of children is different from the number of options that participate
7538               --in combinations, need to generate exclude. Note that this condition work in
7539               --all cases, bom and non-bom, as non-bom children of a bom are considered as
7540               --participating options - Developer allows to select them for combinations.
7541 
7542               --We will be adding another contraint which may have it's own ForAll.
7543 
7544               h_instancequantifiers.DELETE;
7545               t_instancequantifiers.DELETE;
7546 
7547               --Also, we need one more model def to call addConstraint.
7548 
7549               aload_model_def ( p_component_id );
7550 
7551               --All children directly follow the participant in the structure.
7552 
7553               l_index := l_index + 1;
7554               l_count := 0;
7555 
7556               --The participant cannot be a bom reference, so we don't have to use is_bom.
7557 
7558               IF ( NOT is_bom_node ( l_index )) THEN
7559 
7560                  --This is a feature.
7561                  --Put the participant on stack for whatever method we are going to call.
7562 
7563                  aload_context_node ( l_key, const_context_generic );
7564 
7565                  WHILE ( l_index <= h_psnid_lastchildindex ( l_node_id )) LOOP
7566 
7567                     IF ( NOT hl_options ( i ).EXISTS ( TO_CHAR ( t_psn_psnodeid ( l_index )))) THEN
7568 
7569                        --Push option name as a parameter to intersect.
7570 
7571                        push_variable_name ( t_psn_psnodeid ( l_index ));
7572                        l_count := l_count + 1;
7573 
7574                     END IF;
7575 
7576                     l_index := l_index + 1;
7577 
7578                  END LOOP;
7579 
7580                  IF ( l_count = 1 ) THEN
7581 
7582                     --Just one option, generate contains instead of intersects.
7583 
7584                     emit_invokevirtual ('ISetExprDef.contains(Object)');
7585 
7586                  ELSE
7587 
7588                     create_array ( l_count, h_javatypes ('Object'));
7589                     populate_array ( l_count );
7590                     emit_invokevirtual ('ISetExprDef.intersects(Object[])');
7591 
7592                  END IF;
7593 
7594               ELSE
7595 
7596                  tl_excludes_id.DELETE;
7597 
7598                  --The participant is a bom. All children still directly follow the participant in
7599                  --the structure, but there can also be tokens, so we need to check the parent_id.
7600 
7601                  WHILE ( l_index <= h_psnid_lastchildindex ( l_node_id ) AND t_psn_parentid ( l_index ) = l_node_id ) LOOP
7602 
7603                     l_option_id := t_psn_psnodeid ( l_index );
7604 
7605                     IF ( NOT hl_options ( i ).EXISTS ( TO_CHAR ( l_option_id ))) THEN
7606 
7607                        l_count := l_count + 1;
7608                        tl_excludes_id ( l_count ) := l_option_id ;
7609 
7610                     END IF;
7611 
7612                     l_index := l_index + 1;
7613 
7614                  END LOOP;
7615 
7616                  IF ( l_count > 2 ) THEN
7617 
7618                     --Need this to call AnyTrue.
7619 
7620                     aload_model_def ( p_component_id );
7621 
7622                  END IF;
7623 
7624                  FOR i IN 1..l_count LOOP
7625 
7626                     l_option_id := tl_excludes_id ( i );
7627 
7628                     aload_context_node ( l_key, const_context_generic );
7629                     push_variable ( l_option_id, 'ISingletonExprDef');
7630                     emit_invokevirtual ('ISingletonExprDef.getVarRef(IExprDef)');
7631 
7632                     apply_logical_context ( l_option_id, p_input_context.context_type );
7633 
7634                  END LOOP;
7635 
7636                  --If there's only one excluding option, do nothing. If there's two, call or, otherwise
7637                  --create an array an call AnyTrue.
7638 
7639                  IF ( l_count = 2 ) THEN
7640 
7641                     emit_invokevirtual ('ILogicExprDef.or(ILogicExprDef)');
7642 
7643                  ELSIF ( l_count > 2) THEN
7644 
7645                     create_array ( l_count, h_javatypes ('ILogicExprDef'));
7646                     populate_array ( l_count );
7647                     emit_invokevirtual ('IModelDef.any(ILogicExprDef[])');
7648 
7649                  END IF;
7650               END IF;
7651 
7652               tl_excludes.DELETE;
7653               l_index := 1;
7654 
7655               FOR j IN 1..l_participants LOOP
7656 
7657                  l_exclude_key := TO_CHAR ( p_compat_table.participants ( j ).ps_node_id ) || '-' ||
7658                                   TO_CHAR ( p_compat_table.participants ( j ).model_ref_expl_id );
7659 
7660                  IF ( l_exclude_key <> l_key ) THEN
7661 
7662                     tl_excludes ( l_index ) := l_exclude_key;
7663                     l_index := l_index + 1;
7664 
7665                  END IF;
7666               END LOOP;
7667 
7668               IF ( tl_excludes.COUNT > 2) THEN
7669 
7670                  --We need this to call AllTrue.
7671 
7672                  aload_model_def ( p_component_id );
7673 
7674               END IF;
7675 
7676               --Push all the participants to exclude on the stack.
7677 
7678               FOR j IN 1..tl_excludes.COUNT LOOP
7679 
7680                  aload_context_node ( tl_excludes ( j ), const_context_logical );
7681 
7682               END LOOP;
7683 
7684               --If there is only one participant for exclude, do nothing. If there's two, use 'and',
7685               --otherwise create an array and call AllTrue.
7686 
7687               IF ( tl_excludes.COUNT = 2 ) THEN
7688 
7689                  emit_invokevirtual ('ILogicExprDef.and(ILogicExprDef)');
7690 
7691               ELSIF ( tl_excludes.COUNT > 2 ) THEN
7692 
7693                  create_array ( tl_excludes.COUNT, h_javatypes ('ILogicExprDef'));
7694                  populate_array ( tl_excludes.COUNT );
7695                  emit_invokevirtual ('IModelDef.all(ILogicExprDef[])');
7696 
7697               END IF;
7698 
7699               --Now call the exclude and add the constraint.
7700 
7701               emit_invokevirtual ('ILogicExprDef.excludes(ILogicExprDef)');
7702               set_reason_id ();
7703               add_constraint ();
7704 
7705            END IF; --exclude required.
7706         END LOOP;
7707      END generate_compat_table;
7708      ----------------------------------------------------------------------------------
7709      --If p_emptiness is true, the table is allowed to be empty - no combinations. This
7710      --is true for the primary-optional compat tables.
7711      -- Scope: compile_constraints
7712      PROCEDURE verify_compatibility_table ( p_compat_table IN type_compat_table, p_emptiness IN BOOLEAN ) IS
7713 
7714         l_count       PLS_INTEGER;
7715         l_maximum     PLS_INTEGER;
7716         l_index       PLS_INTEGER;
7717 
7718         hl_parentid   type_data_hashtable;
7719 
7720      BEGIN
7721 
7722         IF ( p_compat_table.participants.COUNT < 2 ) THEN
7723 
7724            --#<verification>
7725            --This error can actually be raised here only for explicit compatibility rules.
7726            --For property-based and design-chart this will be caught earlier. Even if it
7727            --gets here for these types of rules, the message is still relevant.
7728 
7729            report_and_raise_rule_warning (
7730              p_text => CZ_UTILS.GET_TEXT(
7731                      CZ_FCE_W_CT_INCOMPLETE_RULE,
7732                      'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name ),
7733                      'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path)),
7734              p_warning_location => 'verify_compatibility_table' );
7735 
7736         END IF;
7737 
7738         IF (( NOT p_emptiness ) AND p_compat_table.combinations.COUNT = 0 ) THEN
7739 
7740            --#<verification>
7741            --Compatibility table should be not empty. This error can be actually raised here only for
7742            --property-based compatibility rules, not for desing chart or explicit compatibility, so
7743            --the message can be significantly enhanced with property-based specifics specifics.
7744 
7745            -- No valid combinations. Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
7746            report_and_raise_rule_warning (
7747                 CZ_UTILS.GET_TEXT ( CZ_FCE_W_COMPAT_NO_COMB,
7748                   'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name ),
7749                   'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path)),
7750                 'verify_compatibility_table'
7751                );
7752 
7753         END IF;
7754 
7755         --#<verification>
7756         --Only one of the participating features is allowed to have maximum > 1. When we call this procedure
7757         --on compat tables constructed for a design chart, there is a little overhead as the primary feature
7758         --participates in all these tables, and we end up checking its maximum several times.
7759 
7760         l_count := 0;
7761 
7762         FOR i IN 1..p_compat_table.participants.COUNT LOOP
7763 
7764            l_index := h_psnid_backindex ( TO_CHAR ( p_compat_table.participants ( i ).ps_node_id ));
7765            hl_parentid ( TO_CHAR ( t_psn_parentid ( l_index ))) := 1;
7766 
7767            l_maximum := CASE is_bom_node ( l_index ) WHEN TRUE THEN t_psn_maximumselected ( l_index ) ELSE t_psn_maximum ( l_index ) END;
7768 
7769            IF ( l_maximum IS NULL OR l_maximum > 1 ) THEN
7770 
7771               l_count := l_count + 1;
7772 
7773            END IF;
7774         END LOOP;
7775 
7776         --Verify for cyclic relationships in rule definition, when a participant is also a child of another
7777         --participant.
7778 
7779         FOR i IN 1..p_compat_table.participants.COUNT LOOP
7780 
7781            IF ( hl_parentid.EXISTS ( TO_CHAR ( p_compat_table.participants ( i ).ps_node_id ))) THEN
7782               -- Cyclic relationship between compatibility rule participants.  Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
7783               report_and_raise_rule_warning (
7784                 p_text => CZ_UTILS.GET_TEXT(
7785                         CZ_FCE_W_CT_CYCLIC_RELATION,
7786                         'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
7787                         'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path)),
7788                 p_warning_location => 'verify_compatibility_table' );
7789 
7790            END IF;
7791         END LOOP;
7792 
7793         IF ( l_count > 1 ) THEN
7794            -- Only one participant of a compatibility rule is allowed to have non-mutually-exclusive children.  Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
7795            report_and_raise_rule_warning(
7796                 p_text => CZ_UTILS.GET_TEXT(
7797                         CZ_FCE_W_CT_ONLY_ONE_NON_MEXC,
7798                         'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
7799                         'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
7800                 p_warning_location => 'verify_compatibility_table');
7801 
7802         END IF;
7803 
7804         --#<verification>
7805         --All the combination tuples must have the same size.
7806 
7807         --#<optimization>
7808         --This verification may potentially be expensive if there are millions of combinations. As compatibility
7809         --table is built by the compiler itself this verification is not necessary and can be removed when there
7810         --are no bugs in this area.
7811 
7812         IF ( p_compat_table.combinations.COUNT > 0 ) THEN
7813 
7814            l_count := p_compat_table.combinations ( 1 ).COUNT;
7815 
7816            FOR i IN 1..p_compat_table.combinations.COUNT LOOP
7817 
7818               IF ( p_compat_table.combinations ( i ).COUNT <> l_count ) THEN
7819 
7820                  --Every combination should consist of the same number of options.
7821 
7822                  --#<should never happen>
7823                  -- 'Incorrect size of a compatible combination occurred. Compatibility Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
7824                  report_and_raise_rule_sys_warn(
7825                     p_text => GET_NOT_TRANSLATED_TEXT(
7826                             CZ_FCE_SW_CT_INCORRECT_SIZE ),
7827                     p_warning_location => 'verify_compatibility_table');
7828 
7829               END IF;
7830            END LOOP;
7831         END IF;
7832      END verify_compatibility_table;
7833      ----------------------------------------------------------------------------------
7834      -- Scope: compile_constraints
7835      FUNCTION get_table_reference ( p_data_type       IN NUMBER
7836                                   , p_iterator_index  IN PLS_INTEGER
7837                                   , p_property_index  IN PLS_INTEGER
7838                                   ) RETURN VARCHAR2 IS
7839 
7840         l_key   VARCHAR2(4000);
7841 
7842      BEGIN
7843 
7844         l_key := p_iterator_index || ')(i' || p_iterator_index || ')(' || p_property_index || ')';
7845 
7846         IF ( p_data_type IN ( h_datatypes ('integer'), h_datatypes ('decimal'))) THEN
7847 
7848            RETURN 'cz_fce_compile.n_(' || l_key;
7849 
7850         ELSIF ( p_data_type = h_datatypes ('boolean')) THEN
7851 
7852            --We use integer representation of boolean as 0/1.
7853 
7854            RETURN 'cz_fce_compile.b_(' || l_key;
7855 
7856         ELSE
7857 
7858            --For all other type (text and translatable) we use text.
7859 
7860            RETURN 'cz_fce_compile.t_(' || l_key;
7861 
7862         END IF;
7863      END get_table_reference;
7864      ----------------------------------------------------------------------------------
7865      -- Scope: compile_constraints
7866      FUNCTION lookup_parameter_value ( j IN PLS_INTEGER, l_property_id IN NUMBER ) RETURN VARCHAR2 IS
7867 
7868         l_parameter   type_iterator_value;
7869 
7870      BEGIN
7871 
7872         l_parameter := retrieve_parameter ( t_exp_argumentname ( j ));
7873 
7874         CASE l_parameter.value_type WHEN const_valuetype_literal THEN
7875 
7876            IF ( l_parameter.data_type IN ( h_datatypes ('integer'), h_datatypes ('decimal'))) THEN
7877 
7878               RETURN l_parameter.data_num_value;
7879 
7880            ELSE
7881 
7882               RETURN l_parameter.data_value;
7883 
7884            END IF;
7885 
7886         WHEN const_valuetype_node THEN
7887 
7888            RETURN get_property_value ( l_property_id, l_parameter.ps_node_id, l_parameter.model_ref_expl_id );
7889 
7890         ELSE
7891            -- 'In paramater stack invalid value type ^VALUE_TYPE associated with the parameter "^PARAM". Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
7892            report_and_raise_rule_sys_warn(
7893                 p_text => GET_NOT_TRANSLATED_TEXT(
7894                         CZ_FCE_SW_INVAL_VAL_PARAMSTK,
7895                         'VALUE_TYPE', l_parameter.value_type,
7896                         'PARAM', t_exp_argumentname ( j ) ),
7897                 p_warning_location => 'lookup_parameter_value');
7898            RETURN NULL;
7899         END CASE;
7900      END lookup_parameter_value;
7901      ----------------------------------------------------------------------------------
7902      -- Scope: compile_constraints
7903      PROCEDURE generate_parameter ( j IN PLS_INTEGER
7904                                   , p_input_context  IN expression_context
7905                                   , x_output_context IN OUT NOCOPY expression_context
7906                                   ) IS
7907 
7908         l_parameter   type_iterator_value;
7909 
7910      BEGIN
7911 
7912         l_parameter := retrieve_parameter ( t_exp_argumentname ( j ));
7913 
7914         CASE l_parameter.value_type WHEN const_valuetype_literal THEN
7915 
7916            t_exp_datavalue ( j ) := l_parameter.data_value;
7917            t_exp_datanumvalue ( j ) := l_parameter.data_num_value;
7918            t_exp_datatype ( j ) := l_parameter.data_type;
7919 
7920            t_exp_exprtype ( j ) := h_exprtypes ('literal');
7921 
7922            generate_literal ( j, get_literal_value ( j ), l_parameter.data_type, p_input_context, x_output_context );
7923 
7924         WHEN const_valuetype_variable THEN
7925 
7926            aload_register ( l_parameter.data_value );
7927 
7928         WHEN const_valuetype_sysprop THEN
7929 
7930            generate_system_property ( l_parameter.data_num_value, l_parameter.ps_node_id, l_parameter.model_ref_expl_id, p_input_context, x_output_context );
7931 
7932         WHEN const_valuetype_node THEN
7933 
7934            t_exp_psnodeid ( j ) := l_parameter.ps_node_id;
7935            t_exp_modelrefexplid ( j ) := l_parameter.model_ref_expl_id;
7936 
7937            t_exp_exprtype ( j ) := h_exprtypes ('node');
7938 
7939            generate_structure_node ( j, p_input_context, x_output_context );
7940 
7941         WHEN const_valuetype_selection THEN
7942 
7943            t_exp_psnodeid ( j ) := l_parameter.ps_node_id;
7944            t_exp_modelrefexplid ( j ) := l_parameter.model_ref_expl_id;
7945 
7946            IF ( h_exprid_childrenindex.EXISTS ( TO_CHAR ( t_exp_exprnodeid ( j )))) THEN
7947 
7948               l_parameter.data_num_value := get_property_id ( h_exprid_childrenindex ( TO_CHAR ( t_exp_exprnodeid ( j ))));
7949 
7950            END IF;
7951 
7952            generate_selection ( j, l_parameter.data_num_value, p_input_context, x_output_context );
7953 
7954         ELSE
7955            -- 'In paramater stack invalid value type ^VALUE_TYPE associated with the parameter "^PARAM". Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
7956            report_and_raise_rule_sys_warn(
7957                 p_text => GET_NOT_TRANSLATED_TEXT(
7958                         CZ_FCE_SW_INVAL_VAL_PARAMSTK,
7959                         'VALUE_TYPE', l_parameter.value_type,
7960                         'PARAM', t_exp_argumentname ( j ) ),
7961                 p_warning_location => 'generate_parameter');
7962 
7963         END CASE;
7964 
7965         add_argument ( j );
7966 
7967      END generate_parameter;
7968      ----------------------------------------------------------------------------------
7969      -- Scope: compile_constraints
7970      FUNCTION value_string ( j             IN PLS_INTEGER
7971                            , p_data_type   IN NUMBER
7972                            , p_num_value   IN VARCHAR2
7973                            , p_value       IN VARCHAR2 ) RETURN VARCHAR2 IS
7974      BEGIN
7975 
7976         IF ( p_data_type IN ( h_datatypes ('integer'), h_datatypes ('decimal'))) THEN
7977 
7978            RETURN p_num_value;
7979 
7980         ELSIF ( p_data_type = h_datatypes ('text')) THEN
7981 
7982            RETURN '''' || p_value || '''';
7983 
7984         ELSIF ( p_data_type = h_datatypes ('boolean')) THEN
7985 
7986            --In cz_expression_nodes value of a boolean literal is represented by 0 or 1 in data_value.
7987            --Here we are trying to handle cases, when the user writes logical constants explicitly as
7988            --operands to logical operands, for example NOT FALSE.
7989 
7990            IF ( logical_context ( j, NULL )) THEN
7991 
7992               RETURN '(' || CASE p_value WHEN 0 THEN 'FALSE' ELSE 'TRUE' END || ')';
7993 
7994            ELSE
7995 
7996               RETURN p_value;
7997 
7998            END IF;
7999 
8000         ELSE
8001 
8002            RETURN NVL ( p_num_value, '''' || p_value || '''' );
8003 
8004         END IF;
8005      END value_string;
8006      ----------------------------------------------------------------------------------
8007      -- Scope: compile_constraints
8008      FUNCTION parse_where_clause ( j                        IN PLS_INTEGER
8009                                  , p_rule_type              IN PLS_INTEGER
8010                                  , p_index_by_iterator      IN OUT NOCOPY type_data_hashtable
8011                                  , p_property_by_iterator   IN OUT NOCOPY type_datahashtable_table
8012                                  ) RETURN VARCHAR2 IS
8013 
8014         l_property_id         NUMBER;
8015         l_data_type           NUMBER;
8016         l_value               VARCHAR2(4000);
8017         l_key                 VARCHAR2(4000);
8018         l_expr_id             VARCHAR2(4000);
8019 
8020         l_index               PLS_INTEGER;
8021         l_iterator_index      PLS_INTEGER;
8022         l_property_index      PLS_INTEGER;
8023 
8024      BEGIN
8025 
8026        l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
8027 
8028        IF ( t_exp_exprtype ( j ) IN ( h_exprtypes ('argument'), h_exprtypes ('node'))) THEN
8029 
8030           IF ( p_rule_type = const_ruletype_compatible ) THEN
8031 
8032              --This will get the property_id appropriately for user or system property.
8033 
8034              IF ( expr_has_one_child ( l_expr_id )) THEN
8035 
8036                 l_index := h_exprid_childrenindex ( l_expr_id );
8037 
8038              ELSE
8039 
8040                 report_and_raise_rule_sys_warn(
8041                   p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_SNODE_WHERE_LIMITS,
8042                           'EXPR_ID', l_expr_id ),
8043                   p_warning_location => 'parse_where_clause');
8044 
8045              END IF;
8046 
8047           END IF;
8048 
8049           IF ( h_exprid_childrenindex.EXISTS ( l_expr_id )) THEN
8050 
8051              l_property_id := get_property_id ( h_exprid_childrenindex ( l_expr_id ));
8052 
8053           ELSE
8054 
8055              --In a statement forall, iterator can participate in the where clause without any property applied.
8056              --In this case we use property_id = 0 and get data type from the parent operator.
8057 
8058              l_property_id := get_property_id ( j );
8059 
8060           END IF;
8061 
8062           get_property_info ( l_property_id, l_data_type, l_value );
8063 
8064        END IF;
8065 
8066        CASE t_exp_exprtype ( j ) WHEN h_exprtypes ('argument') THEN
8067 
8068           IF ( NOT p_index_by_iterator.EXISTS ( t_exp_argumentname ( j ))) THEN
8069 
8070              --This is an iterator from an outer forall, need to evaluate it to a constant.
8071 
8072              l_value := lookup_parameter_value ( j, l_property_id );
8073              RETURN value_string ( j, l_data_type, l_value, l_value );
8074 
8075           ELSE
8076 
8077              l_iterator_index := p_index_by_iterator ( t_exp_argumentname ( j ));
8078              l_key := TO_CHAR ( l_property_id );
8079 
8080              IF ( p_property_by_iterator.EXISTS ( l_iterator_index ) AND p_property_by_iterator ( l_iterator_index ).EXISTS ( l_key )) THEN
8081 
8082                 l_property_index := p_property_by_iterator ( l_iterator_index )( l_key );
8083 
8084              ELSIF ( NOT p_property_by_iterator.EXISTS ( l_iterator_index )) THEN
8085 
8086                 p_property_by_iterator ( l_iterator_index )( l_key ) := 1;
8087                 l_property_index := 1;
8088 
8089              ELSE
8090 
8091                 l_property_index := p_property_by_iterator ( l_iterator_index ).COUNT + 1;
8092                 p_property_by_iterator ( l_iterator_index )( l_key ) := l_property_index;
8093 
8094              END IF;
8095 
8096              --Depending on the data type, generate reference to corresponding table.
8097 
8098              RETURN get_table_reference ( l_data_type, l_iterator_index, l_property_index );
8099 
8100           END IF;
8101 
8102        WHEN h_exprtypes ('node') THEN
8103 
8104           l_value := get_property_value ( l_property_id, t_exp_psnodeid ( j ), t_exp_modelrefexplid ( j ));
8105           RETURN value_string ( j, l_data_type, l_value, l_value );
8106 
8107        WHEN h_exprtypes ('literal') THEN
8108 
8109           RETURN value_string ( j, t_exp_datatype ( j ), TO_CHAR ( t_exp_datanumvalue ( j )), t_exp_datavalue ( j ));
8110 
8111        WHEN h_exprtypes ('operator') THEN
8112 
8113           IF ( t_exp_templateid ( j ) IN
8114                   ( h_templates ('and')
8115                   , h_templates ('or')
8116                   , h_templates ('equals')
8117                   , h_templates ('notequals')
8118                   , h_templates ('gt')
8119                   , h_templates ('lt')
8120                   , h_templates ('ge')
8121                   , h_templates ('le')
8122                   , h_templates ('add')
8123                   , h_templates ('subtract')
8124                   , h_templates ('multiply')
8125                   , h_templates ('div')
8126                   , h_templates ('doesnotbeginwith')
8127                   , h_templates ('doesnotendwith')
8128                   , h_templates ('doesnotcontain')
8129                   , h_templates ('notlike')
8130                   , h_templates ('concatenate')
8131                   , h_templates ('beginswith')
8132                   , h_templates ('endswith')
8133                   , h_templates ('contains')
8134                   , h_templates ('like')
8135                   , h_templates ('matches')
8136                   , h_templates ('textequals')
8137                   , h_templates ('textnotequals')
8138                   )) THEN
8139 
8140               IF ( expr_has_two_children ( l_expr_id )) THEN
8141 
8142                  l_index := h_exprid_childrenindex ( l_expr_id );
8143 
8144               ELSE
8145 
8146                  report_and_raise_rule_sys_warn(
8147                   p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_RE_ENODE_TWO_CHILD,
8148                           'EXPR_ID', l_expr_id ),
8149                   p_warning_location => 'parse_where_clause');
8150 
8151               END IF;
8152 
8153               RETURN parse_operator ( parse_where_clause ( l_index, p_rule_type, p_index_by_iterator, p_property_by_iterator )
8154                                     , t_exp_templateid ( j )
8155                                     , parse_where_clause ( l_index + 1, p_rule_type, p_index_by_iterator, p_property_by_iterator )
8156                                     );
8157 
8158           ELSIF ( t_exp_templateid ( j ) IN
8159                   ( h_templates ('totext')
8160                   , h_templates ('not')
8161                   , h_templates ('neg')
8162                   )) THEN
8163 
8164               IF ( expr_has_one_child ( l_expr_id )) THEN
8165 
8166                   l_index := h_exprid_childrenindex ( l_expr_id );
8167 
8168               ELSE
8169 
8170                   report_and_raise_rule_sys_warn(
8171                     p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_RE_ENODE_ONE_CHILD,
8172                                'EXPR_ID', l_expr_id ),
8173                     p_warning_location => 'parse_where_clause');
8174 
8175               END IF;
8176 
8177               RETURN parse_operator ( parse_where_clause ( l_index, p_rule_type, p_index_by_iterator, p_property_by_iterator )
8178                                     , t_exp_templateid ( j ), NULL );
8179 
8180           ELSE
8181 
8182               -- 'Unknown operator in the WHERE clause. Rule "^RULE_NAME" in the Model "^MODEL_NAME" ignored.';
8183 
8184               report_and_raise_rule_sys_warn(
8185                 GET_NOT_TRANSLATED_TEXT(CZ_FCE_SW_UKNOWN_OP_IN_COMPAT),
8186                 'parse_where_clause'
8187                );
8188                RETURN NULL;
8189 
8190           END IF;
8191 
8192        ELSE
8193 
8194           -- 'Unknown expression node type in the WHERE clause, expr_node_id "^EXPR_ID". Rule ^RULE_NAME in the model ^MODEL_NAME ignored.';
8195 
8196           report_and_raise_rule_sys_warn(
8197                 p_text => GET_NOT_TRANSLATED_TEXT(
8198                         CZ_FCE_SW_INVAL_E_ID_IN_WHERE,
8199                         'EXPR_ID', l_expr_id ),
8200                 p_warning_location => 'parse_where_clause');
8201           RETURN NULL;
8202 
8203        END CASE;
8204      END parse_where_clause;
8205      ----------------------------------------------------------------------------------
8206      -- Scope: compile_constraints
8207      PROCEDURE generate_statement_forall ( j IN PLS_INTEGER
8208                                          , p_input_context  IN expression_context
8209                                          , x_output_context IN OUT NOCOPY expression_context
8210                                          ) IS
8211 
8212         l_index                  PLS_INTEGER;
8213         l_expr_index             PLS_INTEGER;
8214         l_expression_index       PLS_INTEGER;
8215         l_where_index            PLS_INTEGER;
8216         l_property_index         PLS_INTEGER;
8217         l_count                  PLS_INTEGER;
8218 
8219         l_parsed                 VARCHAR2(32000);
8220         l_expr_id                VARCHAR2(4000);
8221         l_key                    VARCHAR2(4000);
8222         l_value                  VARCHAR2(4000);
8223 
8224         l_data_type              NUMBER;
8225         l_property_id            NUMBER;
8226 
8227         h_index_by_iterator      type_data_hashtable;
8228         h_property_by_iterator   type_datahashtable_table;
8229         t_iterator_table         type_iteratortable_table;
8230         l_iterator               type_iterator_table;
8231         t_argument_table         type_varchar4000_table;
8232         h_distinct_values        type_data_hashtable;
8233 
8234         l_compat                 type_compat_table;
8235 
8236         l_distinct               BOOLEAN;
8237         l_embedded               BOOLEAN;
8238         l_iterator_collect       BOOLEAN;
8239      ----------------------------------------------------------------------------------
8240      -- Scope: generate_statement_forall
8241      FUNCTION generate_iterator ( j IN PLS_INTEGER ) RETURN type_iterator_table IS
8242 
8243         l_expr_id          VARCHAR2(4000);
8244         l_property_id      NUMBER;
8245         l_data_type        NUMBER;
8246         l_value            VARCHAR2(4000);
8247 
8248         l_index            PLS_INTEGER;
8249         l_count            PLS_INTEGER;
8250         l_child            PLS_INTEGER;
8251         l_node_index       PLS_INTEGER;
8252 
8253         l_iterator         type_iterator_table;
8254         t_children         type_iteratornode_table;
8255 
8256         l_input_context    expression_context;
8257         l_output_context   expression_context;
8258 
8259      BEGIN
8260 
8261         l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
8262 
8263         IF ( expr_has_children ( l_expr_id )) THEN
8264 
8265           l_index := h_exprid_childrenindex ( l_expr_id );
8266 
8267         ELSE
8268 
8269           -- 'Incomplete forall rule, empty iterator. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
8270           report_and_raise_rule_sys_warn (
8271                 p_text => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SW_INCOMPLETE_FORALL ),
8272                 p_warning_location => 'generate_iterator');
8273 
8274         END IF;
8275 
8276         WHILE ( t_exp_exprparentid.EXISTS ( l_index ) AND t_exp_exprparentid ( l_index ) = t_exp_exprnodeid ( j )) LOOP
8277 
8278           l_count := l_iterator.COUNT + 1;
8279           t_children.DELETE;
8280 
8281           l_expr_id := TO_CHAR ( t_exp_exprnodeid ( l_index ));
8282 
8283           IF ( t_exp_exprtype ( l_index ) IN ( h_exprtypes ('forall'), h_exprtypes ('foralldistinct'))) THEN
8284 
8285               generate_statement_forall ( l_index, l_input_context, l_output_context );
8286 
8287               FOR i IN 1..c_.combinations.COUNT LOOP
8288 
8289                  --This is a COLLECT in the iterator, there can be only one iterator in it and the expression
8290                  --should resolve to a literal.
8291 
8292                  l_iterator ( l_count ) := c_.combinations ( i )( 1 );
8293                  l_count := l_count + 1;
8294 
8295               END LOOP;
8296 
8297           ELSIF ( h_exprid_childrenindex.EXISTS ( l_expr_id )) THEN
8298 
8299              l_child := h_exprid_childrenindex ( l_expr_id );
8300 
8301              --A strange way to identify options operator or property.
8302 
8303              IF (( t_exp_exprtype ( l_index ) = h_exprtypes ('operator') AND t_exp_templateid ( l_index ) = h_templates ('optionsof')) OR
8304                  ( t_exp_exprtype ( l_child ) = h_exprtypes ('systemproperty') AND t_exp_templateid ( l_child ) = h_templates ('options'))) THEN
8305 
8306                 l_node_index := CASE t_exp_exprtype ( l_index ) WHEN h_exprtypes ('operator') THEN l_child ELSE l_index END;
8307                 t_children := explode_node_children ( t_exp_psnodeid ( l_node_index ), t_exp_modelrefexplid ( l_node_index ), FALSE );
8308 
8309                 FOR i IN 1..t_children.COUNT LOOP
8310 
8311                    l_iterator ( l_count ).value_type := const_valuetype_node;
8312                    l_iterator ( l_count ).ps_node_id := t_children ( i ).ps_node_id;
8313                    l_iterator ( l_count ).model_ref_expl_id := t_children ( i ).model_ref_expl_id;
8314 
8315                    l_count := l_count + 1;
8316 
8317                 END LOOP;
8318 
8319              ELSE
8320 
8321                 IF ( t_exp_psnodeid ( l_index ) IS NULL ) THEN
8322 
8323                    --User or system property can be applied only to a structure node.
8324 
8325                    report_and_raise_rule_warning(
8326                         p_text => GET_NOT_TRANSLATED_TEXT(
8327                                 CZ_FCE_SW_INVALID_PROP_USAGE),
8328                         p_warning_location => 'generate_iterator');
8329 
8330                 END IF;
8331 
8332                 l_property_id := get_property_id ( l_child );
8333 
8334                 IF ( h_runtime_properties.EXISTS ( l_property_id )) THEN
8335 
8336                    --Bug #7348938. We used to generate the expression right here and store the result
8337                    --in iterator value of type variable. Later this variable would be aloaded when
8338                    --generating the forall expression. We could do that because such iterator values
8339                    --cannot participate in the WHERE clause and so we could forget about them until
8340                    --the forall expression is generated. However, this does not work for accumulator
8341                    --rules because target should be generated BEFORE contributors, and so we cannot
8342                    --generate contributors here.
8343 
8344                    l_iterator ( l_count ).value_type := const_valuetype_sysprop;
8345                    l_iterator ( l_count ).ps_node_id := t_exp_psnodeid ( l_index );
8346                    l_iterator ( l_count ).model_ref_expl_id := t_exp_modelrefexplid ( l_index );
8347                    l_iterator ( l_count ).data_num_value := l_property_id;
8348 
8349                 ELSIF ( l_property_id = h_templates ('selection')) THEN
8350 
8351                    l_iterator ( l_count ).value_type := const_valuetype_selection;
8352                    l_iterator ( l_count ).ps_node_id := t_exp_psnodeid ( l_index );
8353                    l_iterator ( l_count ).model_ref_expl_id := t_exp_modelrefexplid ( l_index );
8354 
8355                    l_child := l_child + 1;
8356 
8357                    IF ( t_exp_exprparentid.EXISTS ( l_child ) AND t_exp_exprparentid ( l_child ) = t_exp_exprnodeid ( l_index )) THEN
8358 
8359                       l_iterator ( l_count ).data_num_value := get_property_id ( l_child );
8360 
8361                    END IF;
8362 
8363                 ELSE
8364 
8365                    l_iterator ( l_count ).value_type := const_valuetype_literal;
8366 
8367                    get_property_info ( l_property_id, l_data_type, l_value );
8368                    l_value := get_property_value ( l_property_id, t_exp_psnodeid ( l_index ), t_exp_modelrefexplid ( l_index ));
8369 
8370                    l_iterator ( l_count ).data_type := l_data_type;
8371 
8372                    IF ( l_data_type IN ( h_datatypes ('integer'), h_datatypes ('decimal'))) THEN
8373 
8374                       l_iterator ( l_count ).data_num_value := TO_NUMBER ( l_value );
8375 
8376                    ELSE
8377 
8378                       l_iterator ( l_count ).data_value := l_value;
8379 
8380                    END IF;
8381                 END IF;
8382              END IF;
8383 
8384           ELSIF ( t_exp_exprtype ( l_index ) = h_exprtypes ('literal')) THEN
8385 
8386              l_iterator ( l_count ).value_type := const_valuetype_literal;
8387              l_iterator ( l_count ).data_type := t_exp_datatype ( l_index );
8388 
8389              IF ( t_exp_datatype ( l_index ) IN ( h_datatypes ('integer'), h_datatypes ('decimal'))) THEN
8390 
8391                 l_iterator ( l_count ).data_num_value := t_exp_datanumvalue ( l_index );
8392 
8393              ELSE
8394 
8395                 l_iterator ( l_count ).data_value := t_exp_datavalue ( l_index );
8396 
8397              END IF;
8398 
8399           ELSIF ( t_exp_exprtype ( l_index ) = h_exprtypes ('node')) THEN
8400 
8401              l_iterator ( l_count ).value_type := const_valuetype_node;
8402              l_iterator ( l_count ).ps_node_id := t_exp_psnodeid ( l_index );
8403              l_iterator ( l_count ).model_ref_expl_id := t_exp_modelrefexplid ( l_index );
8404 
8405           ELSE
8406 
8407              --#<should never happen>
8408              report_and_raise_rule_sys_warn(
8409                 p_text => GET_NOT_TRANSLATED_TEXT(
8410                         CZ_FCE_SW_INVALID_EXPR_NODE,
8411                         'EXPR_TYPE', t_exp_exprtype ( l_index ) ),
8412                 p_warning_location => 'generate_iterator');
8413 
8414           END IF;
8415 
8416           l_index := l_index + 1;
8417 
8418         END LOOP;
8419 
8420         RETURN l_iterator;
8421      END generate_iterator;
8422      ----------------------------------------------------------------------------------
8423      BEGIN
8424 
8425         l_distinct := ( t_exp_exprtype ( j ) = h_exprtypes ('foralldistinct'));
8426         l_embedded := ( t_exp_exprparentid ( j ) IS NOT NULL );
8427         l_iterator_collect := ( l_embedded AND t_exp_exprtype ( h_exprid_backindex ( TO_CHAR ( t_exp_exprparentid ( j )))) = h_exprtypes ('iterator'));
8428 
8429         l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
8430 
8431         IF ( expr_has_children ( l_expr_id )) THEN
8432 
8433           l_index := h_exprid_childrenindex ( l_expr_id ) - 1;
8434 
8435         ELSE
8436 
8437           report_and_raise_rule_sys_warn (
8438                 p_text => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SW_RE_ENODE_CHILDREN,
8439                             'EXPR_ID', l_expr_id ),
8440                 p_warning_location => 'generate_statement_forall');
8441 
8442         END IF;
8443 
8444         l_where_index := 0;
8445 
8446         --Find iterator definition indexes and WHERE clause index, and generate all iterators.
8447 
8448         FOR i IN 1..h_exprid_numberofchildren ( l_expr_id ) LOOP
8449 
8450            l_expr_index := l_index + i;
8451 
8452            CASE t_exp_exprtype ( l_expr_index ) WHEN h_exprtypes ('iterator') THEN
8453 
8454               h_index_by_iterator ( t_exp_argumentname ( l_expr_index )) := h_index_by_iterator.COUNT + 1;
8455 
8456               t_iterator_table ( t_iterator_table.COUNT + 1 ) := generate_iterator ( l_expr_index );
8457               t_argument_table ( t_argument_table.COUNT + 1 ) := t_exp_argumentname ( l_expr_index );
8458 
8459            WHEN h_exprtypes ('where') THEN
8460 
8461               IF ( expr_has_children ( TO_CHAR ( t_exp_exprnodeid ( l_expr_index )))) THEN
8462 
8463                 l_where_index := h_exprid_childrenindex ( TO_CHAR ( t_exp_exprnodeid ( l_expr_index )));
8464 
8465               ELSE
8466 
8467                 report_and_raise_rule_sys_warn (
8468                       p_text => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SW_RE_ENODE_CHILDREN,
8469                                   'EXPR_ID', TO_CHAR ( t_exp_exprnodeid ( l_expr_index ))),
8470                       p_warning_location => 'generate_logic_template');
8471 
8472               END IF;
8473 
8474            ELSE
8475 
8476               l_expression_index := l_expr_index;
8477 
8478            END CASE;
8479         END LOOP;
8480 
8481         IF ( l_where_index <> 0 ) THEN
8482 
8483            l_parsed := parse_where_clause ( l_where_index, const_ruletype_forall, h_index_by_iterator, h_property_by_iterator );
8484 
8485         END IF;
8486 
8487         IF ( t_iterator_table.COUNT = 0 ) THEN
8488 
8489            --#<should never happen>
8490            -- 'Incomplete forall rule, empty iterator. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
8491 
8492            report_and_raise_rule_sys_warn(
8493                 p_text => GET_NOT_TRANSLATED_TEXT(
8494                         CZ_FCE_SW_INCOMPLETE_FORALL ),
8495                 p_warning_location => 'generate_statement_forall');
8496 
8497         END IF;
8498 
8499         IF ( l_distinct AND t_iterator_table.COUNT > 1 ) THEN
8500 
8501            -- DISTINCT COLLECT and FOR ALL operations are not supported when there is more than one iterator.  Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
8502 
8503            report_and_raise_rule_warning(
8504                 p_text => CZ_UTILS.GET_TEXT (
8505                         CZ_FCE_W_MORE_THAN_ONE_IT_LIM,
8506                         'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name ),
8507                     'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH (p_component_id, p_model_path)),
8508                 p_warning_location => 'generate_statement_forall');
8509 
8510         END IF;
8511 
8512         c_.participants.DELETE;
8513         c_.combinations.DELETE;
8514 
8515         o_.DELETE;
8516         n_.DELETE;
8517         s_.DELETE;
8518         t_.DELETE;
8519         b_.DELETE;
8520 
8521         FOR i IN 1..t_iterator_table.COUNT LOOP
8522 
8523            s_( i ) := t_iterator_table ( i ).COUNT;
8524 
8525            l_iterator := t_iterator_table ( i );
8526            o_( i ) := l_iterator;
8527 
8528            FOR ii IN 1..s_( i ) LOOP
8529 
8530               IF ( l_parsed IS NOT NULL AND h_property_by_iterator.EXISTS ( i )) THEN
8531 
8532                  --h_property_by_iterator ( i ) value would exist only for iterators that are referenced
8533                  --in the WHERE clause. If an iterator is not referenced, we don't need it here.
8534 
8535                  l_key := h_property_by_iterator ( i ).FIRST;
8536 
8537                  WHILE ( l_key IS NOT NULL ) LOOP
8538 
8539                     l_property_id := TO_NUMBER ( l_key );
8540                     l_property_index := h_property_by_iterator ( i )( l_key );
8541                     get_property_info ( l_property_id, l_data_type, l_value );
8542 
8543                     --Populate corresponding arrays if there is a WHERE clause.
8544 
8545                     IF ( l_property_id IN ( h_datatypes ('decimal'), h_datatypes ('boolean'), h_datatypes ('text'))) THEN
8546 
8547                        --Iterator is referenced without any property applied.
8548 
8549                        IF ( l_data_type IN ( h_datatypes ('integer'), h_datatypes ('decimal'))) THEN
8550 
8551                           --The iterator was referenced in the where clause without explicit property applied.
8552                           --For now, allow this only for literals. Later we can set up applying 'default'
8553                           --properties for nodes. However, applying default would be equivalent to allowing
8554                           --dynamic properties in the where clause, because default property is either State()
8555                           --or Quantity(), so we probably will not do that.
8556 
8557                           IF ( l_iterator ( ii ).value_type <> const_valuetype_literal ) THEN
8558 
8559                              -- Incorrect COLLECT or FOR ALL Rule: The conditional expression in the WHERE clause must be static. A dynamic source for
8560                              -- a value provided for iterator ^ITER was detected.  Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
8561 
8562                              report_and_raise_rule_warning(
8563                                 p_text => CZ_UTILS.GET_TEXT (
8564                                         CZ_FCE_W_DYNAMIC_ITERATOR,
8565                                    'ITER', t_argument_table ( i ),
8566                                    'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name ),
8567                                    'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH ( p_component_id, p_model_path )),
8568                                 p_warning_location => 'generate_statement_forall');
8569 
8570                           END IF;
8571 
8572                           --Need the case below because boolean literals can participate in numeric context
8573                           --and so the data type of the implicit property would be assumed as numeric.
8574 
8575                           n_( i )( ii )( l_property_index ) :=
8576                                  CASE l_iterator ( ii ).data_type
8577                                      WHEN h_datatypes ('boolean') THEN TO_NUMBER ( l_iterator ( ii ).data_value )
8578                                      ELSE l_iterator ( ii ).data_num_value END;
8579 
8580                        ELSIF ( l_data_type = h_datatypes ('boolean')) THEN
8581 
8582                           --We use integer representation of boolean as 0/1.
8583 
8584                           b_( i )( ii )( l_property_index ) := TO_NUMBER ( l_iterator ( ii ).data_value );
8585 
8586                        ELSE
8587 
8588                           --For all other types (text and translatable) we use text.
8589 
8590                           t_( i )( ii )( l_property_index ) := l_iterator ( ii ).data_value;
8591 
8592                        END IF;
8593 
8594                     ELSE
8595 
8596                        --This is an actual system or user property. It can only be applied to a node.
8597                        --Later this verification can be removed.
8598 
8599                        IF ( l_iterator ( ii ).value_type <> const_valuetype_node ) THEN
8600 
8601                           --#<should never happen>
8602                           -- 'Found invalid iterator value type "^VALUE". Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
8603                           report_and_raise_rule_sys_warn(
8604                                 p_text => GET_NOT_TRANSLATED_TEXT(
8605                                         CZ_FCE_SW_INVALID_IT_VALUE,
8606                                         'VALUE', l_iterator ( ii ).value_type),
8607                                 p_warning_location => 'generate_statement_forall');
8608 
8609                        END IF;
8610 
8611                        l_value := get_property_value ( l_property_id, l_iterator ( ii ).ps_node_id, l_iterator (ii).model_ref_expl_id );
8612 
8613                        IF ( l_data_type IN ( h_datatypes ('integer'), h_datatypes ('decimal'))) THEN
8614 
8615                           n_( i )( ii )( l_property_index ) := TO_NUMBER ( l_value );
8616 
8617                        ELSIF ( l_data_type = h_datatypes ('boolean')) THEN
8618 
8619                           --We use integer representation of boolean as 0/1.
8620 
8621                           b_( i )( ii )( l_property_index ) := TO_NUMBER ( l_value );
8622 
8623                        ELSE
8624 
8625                           --For all other types (text and translatable) we use text.
8626 
8627                           t_( i )( ii )( l_property_index ) := l_value;
8628 
8629                        END IF;
8630                     END IF;
8631 
8632                     l_key := h_property_by_iterator ( i ).NEXT ( l_key );
8633 
8634                  END LOOP;
8635               END IF;
8636            END LOOP;
8637         END LOOP;
8638 
8639         EXECUTE IMMEDIATE build_executable ( t_iterator_table.COUNT, l_parsed );
8640 
8641         IF ( l_iterator_collect ) THEN
8642 
8643            --This is a collect within an iterator of an outer forall, it can only have single
8644            --iterator, and the expression can only be the iterator with or without static
8645            --property applied.
8646 
8647            IF ( h_exprid_childrenindex.EXISTS ( t_exp_exprnodeid ( l_expression_index ))) THEN
8648 
8649                l_property_id := get_property_id ( h_exprid_childrenindex ( t_exp_exprnodeid ( l_expression_index )));
8650                get_property_info ( l_property_id, l_data_type, l_value );
8651 
8652                FOR i IN 1..c_.combinations.COUNT LOOP
8653 
8654                    l_value := get_property_value ( l_property_id, c_.combinations ( i )( 1 ).ps_node_id, c_.combinations ( i )( 1 ).model_ref_expl_id  );
8655 
8656                    c_.combinations ( i )( 1 ).value_type := const_valuetype_literal;
8657                    c_.combinations ( i )( 1 ).data_type := l_data_type;
8658 
8659                    IF ( l_data_type IN ( h_datatypes ('integer'), h_datatypes ('decimal'))) THEN
8660 
8661                       c_.combinations ( i )( 1 ).data_num_value := TO_NUMBER ( l_value );
8662 
8663                    ELSE
8664 
8665                       c_.combinations ( i )( 1 ).data_value := l_value;
8666 
8667                    END IF;
8668                END LOOP;
8669 
8670                IF ( l_distinct ) THEN
8671 
8672                   l_compat := c_;
8673                   c_.combinations.DELETE;
8674 
8675                   l_count := 1;
8676 
8677                   FOR i IN 1..l_compat.combinations.COUNT LOOP
8678 
8679                       IF ( l_compat.combinations ( i )( 1 ).value_type <> const_valuetype_literal ) THEN
8680                           -- 'Found non-literal value type in COLLECT DISTINCT. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
8681                           report_and_raise_rule_sys_warn(
8682                             p_text => GET_NOT_TRANSLATED_TEXT(
8683                                     CZ_FCE_SW_NON_LIT_IN_COLLECT),
8684                             p_warning_location => 'generate_statement_forall');
8685 
8686                       END IF;
8687 
8688                       IF ( l_compat.combinations ( i )( 1 ).data_type IN ( h_datatypes ('integer'), h_datatypes ('decimal'))) THEN
8689 
8690                          l_value := TO_CHAR ( l_compat.combinations ( i )( 1 ).data_num_value );
8691 
8692                       ELSE
8693 
8694                          l_value := l_compat.combinations ( i )( 1 ).data_value;
8695 
8696                       END IF;
8697 
8698                       IF ( NOT h_distinct_values.EXISTS ( l_value )) THEN
8699 
8700                          c_.combinations ( l_count )( 1 ) := l_compat.combinations ( i )( 1 );
8701                          l_count := l_count + 1;
8702 
8703                          h_distinct_values ( l_value ) := 1;
8704 
8705                       END IF;
8706                   END LOOP;
8707                END IF;
8708            END IF;
8709 
8710            RETURN;
8711         END IF;
8712 
8713         --Need to copy the result to the local table because of the possibility of embedding.
8714 
8715         l_compat := c_;
8716 
8717         IF ( l_embedded ) THEN
8718 
8719            --The forall is not on the top level so it is a collect. We will not add generated
8720            --expressions as constrains just generate them as arguments to the parent operator,
8721            --therefore we need to adjust the number of children of this operator.
8722 
8723            l_expr_id := TO_CHAR ( t_exp_exprparentid ( j ));
8724            h_exprid_numberofchildren ( l_expr_id ) := h_exprid_numberofchildren ( l_expr_id ) - 1;
8725 
8726         END IF;
8727 
8728         l_count := h_parameter_stack.COUNT + 1;
8729 
8730         FOR i IN 1..l_compat.combinations.COUNT LOOP
8731 
8732            --Put each value from the combination into the parameter stack.
8733 
8734            FOR ii IN 1..t_iterator_table.COUNT LOOP
8735 
8736               h_parameter_stack ( l_count )( t_argument_table ( ii )) := l_compat.combinations ( i )( ii );
8737 
8738            END LOOP;
8739 
8740            clear_argument_table ();
8741 
8742            IF ( NOT l_embedded ) THEN
8743 
8744               --This is a top-level forall, generate it as a set of constraints.
8745 
8746               h_instancequantifiers.DELETE;
8747               t_instancequantifiers.DELETE;
8748 
8749               --Put the ModelDef on the stack for the last addConstraint call.
8750 
8751               aload_model_def ( p_component_id );
8752               generate_expression ( l_expression_index, p_input_context, x_output_context );
8753 
8754               IF (l_output_context.context_type NOT IN ( const_context_accumulation, const_context_heuristics )) THEN
8755 
8756                  set_reason_id ();
8757                  add_constraint ();
8758 
8759               ELSE
8760 
8761                  --In case of accumulator rule, we need to remove the model def, put on the stack
8762                  --before expression generation, as we did not add the constraint yet.
8763                  --In the case of ForAll all the constraints are already added so we also need to
8764                  --remove the model def.
8765 
8766                  emit_pop ( 1 );
8767 
8768               END IF;
8769 
8770            ELSE
8771 
8772               --The forall is not on the top level, therefore it is a collect.
8773 
8774               generate_expression ( l_expression_index, p_input_context, x_output_context );
8775               h_exprid_numberofchildren ( l_expr_id ) := h_exprid_numberofchildren ( l_expr_id ) + 1;
8776 
8777            END IF;
8778 
8779            --When generating parameters, we change the expression type of parameter node to the
8780            --type of the retrieved argument and keep it during the expression generation. After
8781            --that we need to restore the argument type for the next iteration.
8782 
8783            restore_arguments ();
8784 
8785         END LOOP;
8786 
8787         h_parameter_stack.DELETE ( l_count );
8788         x_output_context.context_type := const_context_forall;
8789 
8790      END generate_statement_forall;
8791      ----------------------------------------------------------------------------------
8792      -- Scope: compile_constraints
8793      PROCEDURE generate_compatible ( j IN PLS_INTEGER
8794                                    , p_input_context  IN expression_context
8795                                    , x_output_context IN OUT NOCOPY expression_context
8796                                    ) IS
8797 
8798         l_property_index         PLS_INTEGER;
8799         l_data_type              NUMBER;
8800         l_property_id            NUMBER;
8801         l_key                    VARCHAR2(4000);
8802         l_value                  VARCHAR2(4000);
8803         l_parsed                 VARCHAR2(32000);
8804 
8805         h_index_by_iterator      type_data_hashtable;
8806         h_property_by_iterator   type_datahashtable_table;
8807         t_children               type_iteratornode_table;
8808      ----------------------------------------------------------------------------------
8809      -- Scope: generate_compatible
8810      FUNCTION parse_template_application ( j IN PLS_INTEGER ) RETURN VARCHAR2 IS
8811 
8812         l_index               PLS_INTEGER;
8813         l_expr_index          PLS_INTEGER;
8814         l_operator            PLS_INTEGER;
8815         l_expr_id             VARCHAR2(4000);
8816 
8817         l_property_id         NUMBER;
8818         l_data_type           NUMBER;
8819         l_def_value           VARCHAR2(4000);
8820 
8821         l_left_key            VARCHAR2(4000);
8822         l_right_key           VARCHAR2(4000);
8823 
8824         l_if                  VARCHAR2(32000);
8825 
8826      BEGIN
8827 
8828         --This procedure parses a simple Property-based Compatibility template application
8829         --and prepares memory tables necessary for generation.
8830         --It returns the 'if' condition generated from the 'where' clause.
8831 
8832         --The template application specifies the following parameters:
8833 
8834         -- param_index = 1: first participant
8835         -- param_index = 2: property applied to the first participant
8836         -- param_index = 3: compatibility operator
8837         -- param_index = 4: second participant
8838         -- param_index = 5: property applied to the second participant
8839 
8840         l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
8841 
8842         IF ( expr_has_children ( l_expr_id )) THEN
8843 
8844           l_index := h_exprid_childrenindex ( l_expr_id ) - 1;
8845 
8846         ELSE
8847 
8848           -- Incomplete simple Property-based Compatibility rule. Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
8849           report_and_raise_rule_warning (
8850                 p_text => CZ_UTILS.GET_TEXT(
8851                                 CZ_FCE_W_INCOMPLETE_PROPBASED,
8852                                 'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
8853                                 'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path)),
8854                 p_warning_location => 'parse_template_application');
8855 
8856         END IF;
8857 
8858         --Parse the template application.
8859 
8860         FOR i IN 1..h_exprid_numberofchildren ( l_expr_id ) LOOP
8861 
8862            l_expr_index := l_index + i;
8863 
8864            CASE t_exp_paramindex ( l_expr_index )
8865 
8866                WHEN 1 THEN
8867 
8868                   --First participant.
8869                   -- 'Invalid parameter of type "^EXPR_TYPE" specified for the "^ARG_LOCATION" argument of the property-based compatibility template application. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
8870                   IF ( t_exp_exprtype ( l_expr_index ) <> h_exprtypes ('node')) THEN
8871 
8872                      report_and_raise_rule_sys_warn(
8873                         p_text => GET_NOT_TRANSLATED_TEXT(
8874                                 CZ_FCE_SW_INVALID_ARG_PARAM,
8875                                 'EXPR_TYPE', t_exp_exprtype ( l_expr_index ),
8876                                 'ARG_LOCATION', 'first' ),
8877                         p_warning_location => 'parse_template_application');
8878 
8879                   END IF;
8880 
8881                   c_.participants ( 1 ).ps_node_id := t_exp_psnodeid ( l_expr_index );
8882                   c_.participants ( 1 ).model_ref_expl_id := t_exp_modelrefexplid ( l_expr_index );
8883 
8884                WHEN 2 THEN
8885 
8886                   --First property.
8887 
8888                   IF ( t_exp_exprtype ( l_expr_index ) NOT IN ( h_exprtypes ('literal'), h_exprtypes ('property'), h_exprtypes ('systemproperty'))) THEN
8889                      -- 'Invalid parameter of type "^EXPR_TYPE" specified for the "^ARG_LOCATION" argument of the property-based compatibility template application. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
8890                      report_and_raise_rule_sys_warn(
8891                         p_text => GET_NOT_TRANSLATED_TEXT(
8892                                 CZ_FCE_SW_INVALID_ARG_PARAM,
8893                                 'EXPR_TYPE', t_exp_exprtype ( l_expr_index ),
8894                                 'ARG_LOCATION', 'second' ),
8895                         p_warning_location => 'parse_template_application');
8896 
8897                   ELSIF ( t_exp_exprtype ( l_expr_index ) = h_exprtypes ('literal') AND t_exp_propertyid ( i ) IS NULL ) THEN
8898                      -- 'Property is not defined. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
8899                      report_and_raise_rule_sys_warn(
8900                             p_text => GET_NOT_TRANSLATED_TEXT(
8901                                 CZ_FCE_SW_PROP_NOT_DEFINED,
8902                                 'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name)),
8903                             p_warning_location => 'parse_template_application');
8904 
8905                   END IF;
8906 
8907                   l_property_id := get_property_id ( l_expr_index );
8908                   get_property_info ( l_property_id, l_data_type, l_def_value );
8909 
8910                   h_property_by_iterator ( 1 )( TO_CHAR ( l_property_id )) := 1;
8911                   l_left_key := get_table_reference ( l_data_type, 1, 1 );
8912 
8913                WHEN 3 THEN
8914 
8915                   --The operator is specified by name.
8916 
8917                   IF ( t_exp_exprtype ( l_expr_index ) NOT IN ( h_exprtypes ('template'), h_exprtypes ('operator'), h_exprtypes ('operatorbyname'))) THEN
8918                      -- 'Invalid parameter of type "^EXPR_TYPE" specified for the "^ARG_LOCATION" argument of the property-based compatibility template application. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
8919                      report_and_raise_rule_sys_warn(
8920                         p_text => GET_NOT_TRANSLATED_TEXT(
8921                                 CZ_FCE_SW_INVALID_ARG_PARAM,
8922                                 'EXPR_TYPE', t_exp_exprtype ( l_expr_index ),
8923                                 'ARG_LOCATION', 'third' ),
8924                         p_warning_location => 'parse_template_application');
8925 
8926                   END IF;
8927 
8928                   l_operator := CASE t_exp_exprtype ( l_expr_index )
8929                        WHEN h_exprtypes ('operatorbyname') THEN h_templates ( LOWER ( t_exp_argumentname ( l_expr_index )))
8930                        ELSE t_exp_templateid ( l_expr_index ) END;
8931 
8932                WHEN 4 THEN
8933 
8934                   --Second participant.
8935 
8936                   IF ( t_exp_exprtype ( l_expr_index ) <> h_exprtypes ('node')) THEN
8937                      -- 'Invalid parameter of type "^EXPR_TYPE" specified for the "^ARG_LOCATION" argument of the property-based compatibility template application. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
8938                      report_and_raise_rule_sys_warn(
8939                         p_text => GET_NOT_TRANSLATED_TEXT(
8940                                 CZ_FCE_SW_INVALID_ARG_PARAM,
8941                                 'EXPR_TYPE', t_exp_exprtype ( l_expr_index ),
8942                                 'ARG_LOCATION', 'forth' ),
8943                         p_warning_location => 'parse_template_application');
8944 
8945                   END IF;
8946 
8947                   c_.participants ( 2 ).ps_node_id := t_exp_psnodeid ( l_expr_index );
8948                   c_.participants ( 2 ).model_ref_expl_id := t_exp_modelrefexplid ( l_expr_index );
8949 
8950                WHEN 5 THEN
8951 
8952                   --Second property.
8953 
8954                   IF ( t_exp_exprtype ( l_expr_index ) NOT IN ( h_exprtypes ('literal'), h_exprtypes ('property'), h_exprtypes ('systemproperty'))) THEN
8955                      -- 'Invalid parameter of type "^EXPR_TYPE" specified for the "^ARG_LOCATION" argument of the property-based compatibility template application. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
8956                      report_and_raise_rule_sys_warn(
8957                         p_text => GET_NOT_TRANSLATED_TEXT(
8958                                 CZ_FCE_SW_INVALID_ARG_PARAM,
8959                                 'EXPR_TYPE', t_exp_exprtype ( l_expr_index ),
8960                                 'ARG_LOCATION', 'fifth' ),
8961                         p_warning_location => 'parse_template_application');
8962 
8963                   ELSIF ( t_exp_exprtype ( l_expr_index ) = h_exprtypes ('literal') AND t_exp_propertyid ( i ) IS NULL ) THEN
8964                      -- 'Property is not defined. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
8965                      report_and_raise_rule_sys_warn(
8966                             p_text => GET_NOT_TRANSLATED_TEXT(
8967                                 CZ_FCE_SW_PROP_NOT_DEFINED),
8968                             p_warning_location => 'parse_template_application');
8969 
8970                   END IF;
8971 
8972                   l_property_id := get_property_id ( l_expr_index );
8973                   get_property_info ( l_property_id, l_data_type, l_def_value );
8974 
8975                   h_property_by_iterator ( 2 )( TO_CHAR ( l_property_id )) := 1;
8976                   l_right_key := get_table_reference ( l_data_type, 2, 1 );
8977 
8978            END CASE;
8979         END LOOP;
8980 
8981         RETURN parse_operator ( l_left_key, l_operator, l_right_key );
8982      END parse_template_application;
8983      ----------------------------------------------------------------------------------
8984      -- Scope: generate_compatible
8985      FUNCTION parse_statement_compatible ( j IN PLS_INTEGER ) RETURN VARCHAR2 IS
8986 
8987         l_index               PLS_INTEGER;
8988         l_expr_index          PLS_INTEGER;
8989         l_participant_index   PLS_INTEGER;
8990         l_where_index         PLS_INTEGER;
8991         l_count               PLS_INTEGER;
8992 
8993         l_if                  VARCHAR2(32000);
8994         l_expr_id             VARCHAR2(4000);
8995 
8996      BEGIN
8997 
8998         l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
8999 
9000         IF ( expr_has_children ( l_expr_id )) THEN
9001 
9002           l_index := h_exprid_childrenindex ( l_expr_id ) - 1;
9003 
9004         ELSE
9005 
9006           report_and_raise_rule_sys_warn (
9007                 p_text => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SW_RE_ENODE_CHILDREN,
9008                             'EXPR_ID', l_expr_id ),
9009                 p_warning_location => 'parse_statement_compatible');
9010 
9011         END IF;
9012 
9013         l_where_index := 0;
9014 
9015         --This is a COMPATIBLE rule. Find iterator definition indexes and WHERE clause index.
9016 
9017         FOR i IN 1..h_exprid_numberofchildren ( l_expr_id ) LOOP
9018 
9019            l_expr_index := l_index + i;
9020 
9021            CASE t_exp_exprtype ( l_expr_index ) WHEN h_exprtypes ('iterator') THEN
9022 
9023               l_count := h_index_by_iterator.COUNT + 1;
9024               h_index_by_iterator ( t_exp_argumentname ( l_expr_index )) := l_count;
9025 
9026               --For A COMPATIBLE, a child of an iterator is always a participant.
9027 
9028               IF ( expr_has_one_child ( TO_CHAR ( t_exp_exprnodeid ( l_expr_index )))) THEN
9029 
9030                 l_participant_index := h_exprid_childrenindex ( TO_CHAR ( t_exp_exprnodeid ( l_expr_index )));
9031 
9032               ELSE
9033 
9034                 report_and_raise_rule_sys_warn(
9035                   p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_RE_ENODE_ONE_CHILD,
9036                           'EXPR_ID', TO_CHAR ( t_exp_exprnodeid ( l_expr_index ))),
9037                   p_warning_location => 'parse_where_clause');
9038 
9039               END IF;
9040 
9041               c_.participants ( l_count ).ps_node_id := t_exp_psnodeid ( l_participant_index );
9042               c_.participants ( l_count ).model_ref_expl_id := t_exp_modelrefexplid ( l_participant_index );
9043 
9044           WHEN h_exprtypes ('where') THEN
9045 
9046               IF ( expr_has_children ( TO_CHAR ( t_exp_exprnodeid ( l_expr_index )))) THEN
9047 
9048                 l_where_index := h_exprid_childrenindex ( TO_CHAR ( t_exp_exprnodeid ( l_expr_index )));
9049 
9050               ELSE
9051 
9052                 report_and_raise_rule_sys_warn (
9053                       p_text => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SW_RE_ENODE_CHILDREN,
9054                                   'EXPR_ID', TO_CHAR ( t_exp_exprnodeid ( l_expr_index ))),
9055                       p_warning_location => 'parse_statement_compatible');
9056 
9057               END IF;
9058 
9059           ELSE
9060 
9061               --#<should never happen>
9062               -- 'Invalid structure of a compatibility rule. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
9063               report_and_raise_rule_sys_warn(
9064                     p_text => GET_NOT_TRANSLATED_TEXT(
9065                         CZ_FCE_SW_INVALID_STRUCTURE),
9066                     p_warning_location => 'parse_statement_compatible');
9067 
9068           END CASE;
9069         END LOOP;
9070 
9071         IF ( h_index_by_iterator.COUNT = 0 ) THEN
9072 
9073            --#<should never happen>
9074            -- 'No iterator specified. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
9075            report_and_raise_rule_sys_warn(
9076                     p_text => GET_NOT_TRANSLATED_TEXT(
9077                         CZ_FCE_SW_NO_ITERATOR ),
9078                     p_warning_location => 'parse_statement_compatible');
9079 
9080         END IF;
9081 
9082         IF ( l_where_index <> 0 ) THEN
9083 
9084            l_if := parse_where_clause ( l_where_index, const_ruletype_compatible, h_index_by_iterator, h_property_by_iterator );
9085 
9086         END IF;
9087         RETURN l_if;
9088 
9089      END parse_statement_compatible;
9090      ----------------------------------------------------------------------------------
9091      BEGIN --> generate_compatible
9092 
9093         c_.participants.DELETE;
9094         c_.combinations.DELETE;
9095 
9096         o_.DELETE;
9097         n_.DELETE;
9098         s_.DELETE;
9099         t_.DELETE;
9100         b_.DELETE;
9101 
9102         IF ( t_exp_exprtype ( j ) = h_exprtypes ('compatible')) THEN
9103 
9104            l_parsed := parse_statement_compatible ( j );
9105 
9106         ELSE
9107 
9108            l_parsed := parse_template_application ( j );
9109 
9110         END IF;
9111 
9112         --Read all the property values and populate the arrays.
9113 
9114         FOR i IN 1..c_.participants.COUNT LOOP
9115 
9116           l_key := h_property_by_iterator ( i ).FIRST;
9117           t_children := explode_node_children ( c_.participants ( i ).ps_node_id, c_.participants ( i ).model_ref_expl_id, FALSE );
9118 
9119           WHILE ( l_key IS NOT NULL ) LOOP
9120 
9121              l_property_id := TO_NUMBER ( l_key );
9122 
9123              get_property_info ( l_property_id, l_data_type, l_value );
9124              l_property_index := h_property_by_iterator ( i )( l_key );
9125 
9126              FOR ii IN 1..t_children.COUNT LOOP
9127 
9128                 o_( i )( ii ).ps_node_id := t_children ( ii ).ps_node_id;
9129 
9130                 IF ( l_parsed IS NOT NULL ) THEN
9131 
9132                    --We need to actually get the property values and populate corresponding arrays only if there
9133                    --is a WHERE clause. Probably, a compatibility rule without a WHERE clause should be reported.
9134 
9135                    l_value := get_property_value ( l_property_id, t_children ( ii ).ps_node_id, t_children ( ii ).model_ref_expl_id );
9136 
9137                    IF ( l_data_type IN ( h_datatypes ('integer'), h_datatypes ('decimal'))) THEN
9138 
9139                       n_( i )( ii )( l_property_index ) := TO_NUMBER ( l_value );
9140 
9141                    ELSIF ( l_data_type = h_datatypes ('boolean')) THEN
9142 
9143                       --We use integer representation of boolean as 0/1.
9144 
9145                       b_( i )( ii )( l_property_index ) := TO_NUMBER ( l_value );
9146 
9147                    ELSE
9148 
9149                       --For all other types (text and translatable) we use text.
9150 
9151                       t_( i )( ii )( l_property_index ) := l_value;
9152 
9153                    END IF;
9154                 END IF;
9155              END LOOP;
9156 
9157              s_( i ) := t_children.COUNT;
9158              l_key := h_property_by_iterator ( i ).NEXT ( l_key );
9159 
9160           END LOOP;
9161         END LOOP;
9162 
9163         --This will populate the table of combinations.
9164 
9165         EXECUTE IMMEDIATE build_executable ( c_.participants.COUNT, l_parsed );
9166         verify_compatibility_table ( c_, FALSE );
9167 
9168         --Now generate the compatibility table.
9169 
9170         generate_compat_table ( c_, p_input_context, x_output_context );
9171         x_output_context.context_type := const_context_compatible;
9172 
9173      END generate_compatible;
9174      ----------------------------------------------------------------------------------
9175      -- Scope: compile_constraints
9176      PROCEDURE generate_explicit_compat ( p_input_context  IN expression_context
9177                                         , x_output_context IN OUT NOCOPY expression_context
9178                                         ) IS
9179 
9180         tl_modelrefexplid   type_number_table;
9181         tl_featureid        type_number_table;
9182         tl_primaryoptid     type_number_table;
9183         tl_secondaryoptid   type_number_table;
9184 
9185         l_compat_table      type_compat_table;
9186         hl_features         type_data_hashtable;
9187 
9188         l_key               VARCHAR2(4000);
9189         l_count             PLS_INTEGER;
9190 
9191      BEGIN
9192 
9193         --We don't even need cz_des_chart_features table for explicit compatibility. Here we read all the data
9194         --in bulk and then transform it into another form in memory. This way we don't need any SQL ordering.
9195 
9196         SELECT primary_opt_id, secondary_opt_id, secondary_feature_id, secondary_feat_expl_id
9197           BULK COLLECT INTO tl_primaryoptid, tl_secondaryoptid, tl_featureid, tl_modelrefexplid
9198           FROM cz_des_chart_cells
9199          WHERE deleted_flag = '0'
9200            AND rule_id = this_rule_id;
9201 
9202         FOR i IN 1..tl_primaryoptid.COUNT LOOP
9203 
9204             --We are using the same key as for storing context nodes in local variables because we will be
9205             --storing and loading nodes when generating compatibility table.
9206 
9207            l_key := tl_featureid ( i ) || '-' || tl_modelrefexplid ( i );
9208 
9209            IF ( NOT hl_features.EXISTS ( l_key )) THEN
9210 
9211               l_count := l_compat_table.participants.COUNT + 1;
9212               hl_features ( l_key ) := l_count;
9213 
9214               l_compat_table.participants ( l_count ).ps_node_id := tl_featureid ( i );
9215               l_compat_table.participants ( l_count ).model_ref_expl_id := tl_modelrefexplid ( i );
9216 
9217            ELSE
9218 
9219               l_count := hl_features ( l_key );
9220 
9221            END IF;
9222 
9223            l_compat_table.combinations ( tl_primaryoptid ( i ))( l_count ).ps_node_id := tl_secondaryoptid ( i );
9224 
9225         END LOOP;
9226 
9227         verify_compatibility_table ( l_compat_table, FALSE );
9228 
9229         --Now generate the compatibility table.
9230 
9231         generate_compat_table ( l_compat_table, p_input_context, x_output_context );
9232 
9233      END generate_explicit_compat;
9234      ----------------------------------------------------------------------------------
9235      -- Scope: compile_constraints
9236      PROCEDURE generate_design_chart ( p_input_context  IN expression_context
9237                                      , x_output_context IN OUT NOCOPY expression_context
9238                                      ) IS
9239 
9240         tl_modelrefexplid        type_number_table;
9241         tl_featureid             type_number_table;
9242         tl_featuretype           type_number_table;
9243         tl_primaryoptid          type_number_table;
9244         tl_secondaryoptid        type_number_table;
9245         tl_secondaryfeatid       type_number_table;
9246         tl_secondaryfeatexplid   type_number_table;
9247 
9248         tl_primary               type_iteratornode_table;
9249         tl_defining              type_iteratornode_table;
9250         tl_optional              type_iteratornode_table;
9251 
9252         hl_combinations          type_nodehashtable_hashtable;
9253         h_comb_number            type_data_hashtable;
9254 
9255         l_compat_tables          type_compattable_table;
9256         l_count                  PLS_INTEGER;
9257         l_index                  PLS_INTEGER;
9258         l_compat_index           PLS_INTEGER;
9259         l_combinations           PLS_INTEGER;
9260 
9261         l_key                    VARCHAR2(4000);
9262         l_primary_key            VARCHAR2(4000);
9263 
9264      BEGIN
9265 
9266         SELECT feature_id, model_ref_expl_id, feature_type
9267           BULK COLLECT INTO tl_featureid, tl_modelrefexplid, tl_featuretype
9268           FROM cz_des_chart_features
9269          WHERE deleted_flag = '0'
9270            AND rule_id = this_rule_id;
9271 
9272         IF ( tl_featureid.COUNT = 0 ) THEN
9273            -- Design chart is empty.  Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
9274            report_and_raise_rule_warning(
9275                 p_text => CZ_UTILS.GET_TEXT(
9276                         CZ_FCE_W_EMPTY_DESIGN_CHART,
9277                         'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
9278                         'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
9279                 p_warning_location => 'generate_design_chart' );
9280 
9281         END IF;
9282 
9283         FOR i IN 1..tl_featureid.COUNT LOOP
9284 
9285             IF ( tl_featuretype ( i ) = h_designtypes('primary')) THEN
9286 
9287                l_count := tl_primary.COUNT + 1;
9288 
9289                tl_primary ( l_count ).ps_node_id := tl_featureid ( i );
9290                tl_primary ( l_count ).model_ref_expl_id := tl_modelrefexplid ( i );
9291 
9292             ELSIF ( tl_featuretype ( i ) = h_designtypes('defining')) THEN
9293 
9294                l_count := tl_defining.COUNT + 1;
9295 
9296                tl_defining ( l_count ).ps_node_id := tl_featureid ( i );
9297                tl_defining ( l_count ).model_ref_expl_id := tl_modelrefexplid ( i );
9298 
9299             ELSIF ( tl_featuretype ( i ) = h_designtypes('optional')) THEN
9300 
9301                l_count := tl_optional.COUNT + 1;
9302 
9303                tl_optional ( l_count ).ps_node_id := tl_featureid ( i );
9304                tl_optional ( l_count ).model_ref_expl_id := tl_modelrefexplid ( i );
9305 
9306             ELSE
9307                -- 'Found invalid feature type "^FEAT_TYPE". Design Chart Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
9308                report_and_raise_rule_sys_warn(
9309                 p_text => GET_NOT_TRANSLATED_TEXT(
9310                         CZ_FCE_SW_INVAL_FEAT_TYPE_DC,
9311                         'FEAT_TYPE', tl_featuretype ( i )
9312                         ),
9313                 p_warning_location => 'generate_design_chart' );
9314 
9315             END IF;
9316         END LOOP;
9317 
9318         IF ( tl_primary.COUNT <> 1 ) THEN
9319            -- The primary feature in the design chart is either missing or duplicated.  Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
9320            report_and_raise_rule_warning(
9321                 p_text => CZ_UTILS.GET_TEXT(
9322                         CZ_FCE_W_NO_PRIMARY_FEAT_DC,
9323                         'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
9324                         'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path)),
9325                 p_warning_location => 'generate_design_chart' );
9326 
9327         END IF;
9328 
9329         IF ( tl_defining.COUNT = 0 AND tl_optional.COUNT = 0) THEN
9330 
9331            report_and_raise_rule_warning(
9332                 p_text => CZ_UTILS.GET_TEXT(
9333                         CZ_FCE_W_EMPTY_DESIGN_CHART,
9334                         'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
9335                         'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
9336                 p_warning_location => 'generate_design_chart' );
9337 
9338         END IF;
9339 
9340         SELECT primary_opt_id, secondary_opt_id, secondary_feature_id, secondary_feat_expl_id
9341           BULK COLLECT INTO tl_primaryoptid, tl_secondaryoptid, tl_secondaryfeatid, tl_secondaryfeatexplid
9342           FROM cz_des_chart_cells
9343          WHERE deleted_flag = '0'
9344            AND rule_id = this_rule_id;
9345 
9346         FOR i IN 1..tl_primaryoptid.COUNT LOOP
9347 
9348            l_key := TO_CHAR ( tl_secondaryfeatid ( i )) || '-' || TO_CHAR ( tl_secondaryfeatexplid ( i ));
9349            hl_combinations ( l_key )( i ) := tl_secondaryoptid ( i );
9350 
9351         END LOOP;
9352 
9353         l_compat_index := 1;
9354 
9355         IF ( tl_defining.COUNT > 0 ) THEN
9356 
9357            --Build and verify the defining compatibility table.
9358 
9359            l_compat_tables ( l_compat_index ).participants ( 1 ) := tl_primary ( 1 );
9360 
9361            FOR i IN 1..tl_defining.COUNT LOOP
9362 
9363               l_compat_tables ( l_compat_index ).participants ( i + 1 ) := tl_defining ( i );
9364               l_key := TO_CHAR ( tl_defining ( i ).ps_node_id ) || '-' || TO_CHAR ( tl_defining ( i ).model_ref_expl_id );
9365 
9366               IF ( NOT hl_combinations.EXISTS ( l_key )) THEN
9367                  -- No selection made between primary and defining feature in design chart rule. Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
9368                  report_and_raise_rule_warning(
9369                     p_text => CZ_UTILS.GET_TEXT(
9370                             CZ_FCE_W_NO_COMBINATIONS_DC,
9371                             'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
9372                             'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
9373                     p_warning_location => 'generate_design_chart' );
9374 
9375               END IF;
9376 
9377               IF ( i = 1 ) THEN
9378 
9379                  l_combinations := hl_combinations ( l_key ).COUNT;
9380 
9381               ELSE
9382 
9383                  IF ( hl_combinations ( l_key ).COUNT <> l_combinations ) THEN
9384                     -- No one-to-one correspondence between options of primary and defining feature in design chart rule. Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
9385                     report_and_raise_rule_warning(
9386                         p_text => CZ_UTILS.GET_TEXT(
9387                                 CZ_FCE_W_INVALID_NUM_COMB_DC,
9388                                 'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
9389                                 'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
9390                         p_warning_location => 'generate_design_chart' );
9391 
9392                  END IF;
9393               END IF;
9394 
9395               l_index := hl_combinations ( l_key ).FIRST;
9396 
9397               IF ( i = 1 ) THEN
9398 
9399                  --As part of the processing for the first defining feature, we will populate the first position
9400                  --of each combination with corresponding primary option id, and establish a map between primary
9401                  --options and combinations. This map will be used to retrieve the combination number by primary
9402                  --option for other defining features.
9403 
9404                  l_count := 1;
9405 
9406                  WHILE ( l_index IS NOT NULL ) LOOP
9407 
9408                      l_compat_tables ( l_compat_index ).combinations ( l_count )( 1 ).ps_node_id := tl_primaryoptid ( l_index );
9409                      l_compat_tables ( l_compat_index ).combinations ( l_count )( 2 ).ps_node_id := hl_combinations ( l_key )( l_index );
9410 
9411                      --Bug #7519498 - we cannot assume the same order of primary options within each combination
9412                      --because the sql statement does not use any ordering. So, we need to build a map between
9413                      --primary option id(s) and combination numbers.
9414 
9415                      h_comb_number ( TO_CHAR ( tl_primaryoptid ( l_index ))) := l_count;
9416 
9417                      l_index := hl_combinations ( l_key ).NEXT ( l_index );
9418                      l_count := l_count + 1;
9419 
9420                  END LOOP;
9421 
9422               ELSE
9423 
9424                  WHILE ( l_index IS NOT NULL ) LOOP
9425 
9426                      l_count := h_comb_number ( TO_CHAR ( tl_primaryoptid ( l_index )));
9427                      l_compat_tables ( l_compat_index ).combinations ( l_count )( i + 1 ).ps_node_id := hl_combinations ( l_key )( l_index );
9428 
9429                      l_index := hl_combinations ( l_key ).NEXT ( l_index );
9430 
9431                  END LOOP;
9432               END IF;
9433            END LOOP;
9434 
9435            verify_compatibility_table ( l_compat_tables ( l_compat_index ), FALSE );
9436            l_compat_index := l_compat_index + 1;
9437 
9438         END IF; --build defining compatibility table
9439 
9440         --Build all the optional compatibility tables.
9441 
9442         FOR i IN 1..tl_optional.COUNT LOOP
9443 
9444            l_compat_tables ( l_compat_index ).participants ( 1 ) := tl_primary ( 1 );
9445            l_compat_tables ( l_compat_index ).participants ( 2 ) := tl_optional ( i );
9446 
9447            l_key := TO_CHAR ( tl_optional ( i ).ps_node_id ) || '-' || TO_CHAR ( tl_optional ( i ).model_ref_expl_id );
9448 
9449            --For the optional feature there can be no combinations. In this case generate_compat_table
9450            --will generate and exclude relation between the primary and the optional features.
9451 
9452            IF ( hl_combinations.EXISTS ( l_key )) THEN
9453 
9454               l_index := hl_combinations ( l_key ).FIRST;
9455               l_count := 1;
9456 
9457               WHILE ( l_index IS NOT NULL ) LOOP
9458 
9459                  l_compat_tables ( l_compat_index ).combinations ( l_count )( 2 ).ps_node_id := hl_combinations ( l_key )( l_index );
9460                  l_compat_tables ( l_compat_index ).combinations ( l_count )( 1 ).ps_node_id := tl_primaryoptid ( l_index );
9461 
9462                  l_index := hl_combinations ( l_key ).NEXT ( l_index );
9463                  l_count := l_count + 1;
9464 
9465               END LOOP;
9466            END IF;
9467 
9468            verify_compatibility_table ( l_compat_tables ( l_compat_index ), TRUE );
9469            l_compat_index := l_compat_index + 1;
9470 
9471         END LOOP;
9472 
9473         --Generate all the compatibility tables.
9474 
9475         FOR i IN 1..l_compat_tables.COUNT LOOP
9476 
9477            generate_compat_table ( l_compat_tables ( i ), p_input_context, x_output_context );
9478 
9479         END LOOP;
9480      END generate_design_chart;
9481      ----------------------------------------------------------------------------------
9482      -- Scope: compile_constraints
9483      PROCEDURE generate_power ( j IN PLS_INTEGER
9484                               , p_input_context IN expression_context
9485                               , x_output_context IN OUT NOCOPY expression_context
9486                               ) IS
9487 
9488         l_expr_id          VARCHAR2(4000);
9489         l_index            PLS_INTEGER;
9490         l_aux              PLS_INTEGER;
9491 
9492      BEGIN
9493 
9494         l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
9495 
9496         IF ( expr_has_two_children ( l_expr_id )) THEN
9497 
9498            l_index := h_exprid_childrenindex ( l_expr_id );
9499 
9500         ELSE
9501 
9502            -- 'Incomplete power operator. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
9503            report_and_raise_rule_sys_warn(
9504             p_text => GET_NOT_TRANSLATED_TEXT(
9505                                 CZ_FCE_SW_INCOMPLETE_POWER ),
9506             p_warning_location => 'generate_power');
9507 
9508         END IF;
9509 
9510         l_aux := l_index + 1;
9511 
9512         IF ( t_exp_exprtype ( l_aux ) <> h_exprtypes ('literal') OR t_exp_datatype ( l_aux ) <> h_datatypes ('integer')) THEN
9513            -- 'The exponent of the power operaror must be an integer constant. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
9514            report_and_raise_rule_sys_warn(
9515                     p_text => GET_NOT_TRANSLATED_TEXT(
9516                             CZ_FCE_SW_EXP_PWR_MUST_BE_INT ),
9517                     p_warning_location => 'generate_power' );
9518 
9519         END IF;
9520 
9521         generate_expression ( l_index, p_input_context, x_output_context );
9522         generate_expression ( l_aux, p_input_context, x_output_context );
9523 
9524         emit_invokevirtual ('INumExprDef.pow(int)');
9525 
9526      END generate_power;
9527      ----------------------------------------------------------------------------------
9528      -- Scope: compile_constraints
9529      PROCEDURE generate_mathrounding ( j IN PLS_INTEGER
9530                                      , p_input_context IN expression_context
9531                                      , x_output_context IN OUT NOCOPY expression_context
9532                                      ) IS
9533 
9534         l_expr_id          VARCHAR2(4000);
9535         l_index            PLS_INTEGER;
9536         l_aux              PLS_INTEGER;
9537 
9538         l_template_id      NUMBER := t_exp_templateid ( j );
9539 
9540      BEGIN
9541 
9542         l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
9543 
9544         IF ( expr_has_two_children ( l_expr_id )) THEN
9545 
9546            l_index := h_exprid_childrenindex ( l_expr_id );
9547 
9548         ELSE
9549 
9550            -- 'Incomplete math rounding operator. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
9551 
9552            report_and_raise_rule_sys_warn(
9553               p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_INCOMPLETE_MROUND ),
9554               p_warning_location => 'generate_mathrounding');
9555 
9556         END IF;
9557 
9558         l_aux := l_index + 1;
9559 
9560         generate_expression ( l_index, p_input_context, x_output_context );
9561 
9562         IF ( l_template_id = h_templates ('mod')) THEN
9563 
9564            emit_dup ();
9565 
9566         END IF;
9567 
9568         generate_expression ( l_aux, p_input_context, x_output_context );
9569         copyto_local_variable ('var');
9570 
9571         invoke_operator2 ( h_templates ('div'), l_aux, x_output_context );
9572         emit_invokevirtual ( h_mathrounding_ops ( l_template_id ));
9573 
9574         aload_local_variable ('var');
9575         invoke_operator2 ( h_templates ('multiply'), l_aux, x_output_context );
9576 
9577         IF ( l_template_id = h_templates ('mod')) THEN
9578 
9579            emit_invokevirtual ('INumExprDef.diff(INumExprDef)');
9580 
9581         END IF;
9582      END generate_mathrounding;
9583      ----------------------------------------------------------------------------------
9584      PROCEDURE generate_trigonometric ( j IN PLS_INTEGER
9585                                       , p_input_context IN expression_context
9586                                       , x_output_context IN OUT NOCOPY expression_context
9587                                       ) IS
9588 
9589         l_expr_id          VARCHAR2(4000);
9590         l_index            PLS_INTEGER;
9591 
9592         l_template_id      NUMBER := t_exp_templateid ( j );
9593 
9594      BEGIN
9595 
9596         l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
9597 
9598         IF ( expr_has_one_child ( l_expr_id )) THEN
9599 
9600           l_index := h_exprid_childrenindex ( l_expr_id );
9601 
9602         ELSE
9603 
9604           -- 'Incomplete math trigonometric operator. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
9605 
9606           report_and_raise_rule_sys_warn(
9607             p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_INCOMPLETE_TRIG ),
9608             p_warning_location => 'generate_trigonometric');
9609 
9610         END IF;
9611 
9612         generate_expression ( l_index, p_input_context, x_output_context );
9613 
9614         IF ( l_template_id = h_templates ('log')) THEN
9615 
9616            --<log> ::= x.log().div(Solver.literal(10).log())
9617 
9618            emit_invokevirtual ('INumExprDef.log()');
9619 
9620            aload_model_def ( p_component_id );
9621 
9622            emit_code ( h_inst ('bipush') || cz_fce_compile_utils.byte ( 10 ));
9623            emit_invokevirtual('IModelDef.literal(int)');
9624 
9625            emit_invokevirtual ('INumExprDef.log()');
9626            emit_invokevirtual ('INumExprDef.div(INumExprDef)');
9627 
9628         ELSIF ( l_template_id IN ( h_templates ('cosh'), h_templates ('sinh'))) THEN
9629 
9630            --<cosh> ::= (x.exp().sum(x.neg().exp())).div(2)
9631            --<sinh> ::= (x.exp().diff(x.neg().exp())).div(2)
9632 
9633            copyto_local_variable ('var');
9634            emit_invokevirtual ('INumExprDef.exp()');
9635 
9636            aload_local_variable ('var');
9637            emit_invokevirtual ('INumExprDef.neg()');
9638            emit_invokevirtual ('INumExprDef.exp()');
9639 
9640            emit_invokevirtual ('INumExprDef.' || CASE l_template_id WHEN h_templates ('cosh') THEN 'sum' ELSE 'diff' END || '(INumExprDef)');
9641            emit_code ( h_inst ('iconst_2'));
9642            emit_invokevirtual ('INumExprDef.div(int)');
9643 
9644         ELSIF ( l_template_id IN ( h_templates ('sin'), h_templates ('tan'))) THEN
9645 
9646            --<sin> ::= (x.diff(Solver.literal(Math.PI).div(2))).cos()
9647            --<tan> ::= ((x.diff(Solver.literal(Math.PI).div(2))).cos()).div(x.cos())
9648 
9649            IF ( l_template_id = h_templates ('tan')) THEN
9650 
9651               copyto_local_variable ('var');
9652 
9653            END IF;
9654 
9655            aload_model_def ( p_component_id );
9656            emit_constant ( h_mathconstants ('pi'));
9657            emit_invokevirtual('IModelDef.literal(double)');
9658 
9659            emit_code ( h_inst ('iconst_2'));
9660            emit_invokevirtual ('INumExprDef.div(int)');
9661 
9662            emit_invokevirtual ('INumExprDef.diff(INumExprDef)');
9663            emit_invokevirtual ('INumExprDef.cos()');
9664 
9665            IF ( l_template_id = h_templates ('tan')) THEN
9666 
9667               aload_local_variable ('var');
9668               emit_invokevirtual ('INumExprDef.cos()');
9669               emit_invokevirtual ('INumExprDef.div(INumExprDef)');
9670 
9671            END IF;
9672 
9673         ELSIF ( l_template_id = h_templates ('tanh')) THEN
9674 
9675            --<tanh> ::= (((x.prod(2)).exp()).diff(1)).div((((x.prod(2)).exp())).sum(1))
9676 
9677            emit_code ( h_inst ('iconst_2'));
9678            emit_invokevirtual ('INumExprDef.prod(int)');
9679            emit_invokevirtual ('INumExprDef.exp()');
9680 
9681            copyto_local_variable ('var');
9682            emit_code ( h_inst ('iconst_1'));
9683            emit_invokevirtual ('INumExprDef.diff(int)');
9684 
9685            aload_local_variable ('var');
9686            emit_code ( h_inst ('iconst_1'));
9687            emit_invokevirtual ('INumExprDef.sum(int)');
9688 
9689            emit_invokevirtual ('INumExprDef.div(INumExprDef)');
9690 
9691         ELSE
9692            -- 'Mathematical operator is not implemented for template_id "^TEMPL_ID". Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
9693            report_and_raise_rule_sys_warn(
9694               p_text => GET_NOT_TRANSLATED_TEXT(
9695                     CZ_FCE_SW__NO_MATH_OP,
9696                     'TEMPL_ID', l_template_id ),
9697               p_warning_location => 'generate_trigonometric' );
9698 
9699         END IF;
9700      END generate_trigonometric;
9701      ----------------------------------------------------------------------------------
9702      PROCEDURE generate_heuristics ( j IN PLS_INTEGER
9703                                    , p_input_context IN expression_context
9704                                    , x_output_context IN OUT NOCOPY expression_context
9705                                    ) IS
9706 
9707         l_expr_id          VARCHAR2(4000);
9708         l_method           VARCHAR2(4000);
9709         l_key              VARCHAR2(4000);
9710 
9711         l_index            PLS_INTEGER;
9712         l_node_id          NUMBER;
9713         l_property_id      NUMBER;
9714 
9715         l_parameter        type_iterator_value;
9716 
9717      BEGIN
9718 
9719         l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
9720 
9721         IF ( expr_has_one_child ( l_expr_id )) THEN
9722 
9723           l_index := h_exprid_childrenindex ( l_expr_id );
9724 
9725         ELSE
9726 
9727           -- 'Incomplete Default or Search Decision. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
9728           report_and_raise_rule_sys_warn(
9729             p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_INCOMPLETE_SEARCH ),
9730             p_warning_location => 'generate_heuristics');
9731 
9732         END IF;
9733 
9734         -- 'Invalid default or search decision is found. Here operand can only be a structure node. Rule "^RULE_NAME" in the model "^MODEL_NAME" ignored.';
9735 
9736         l_parameter := get_structure_node ( l_index );
9737 
9738         IF ( l_parameter.value_type IS NULL ) THEN
9739 
9740           report_and_raise_rule_sys_warn(
9741                 p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_SD_OPAND_STRUCT_N ),
9742                 p_warning_location => 'generate_heuristics');
9743 
9744         END IF;
9745 
9746         l_node_id := l_parameter.ps_node_id;
9747         l_key := TO_CHAR ( l_node_id );
9748 
9749         IF ( h_psnid_devlprojectid ( l_key ) <> p_component_id ) THEN
9750 
9751            --  Defaults and search decisions cannot be defined across different models.  Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
9752 
9753            report_and_raise_rule_warning(
9754                     p_text => CZ_UTILS.GET_TEXT(
9755                             CZ_FCE_W_SD_NOT_ACROSS_MODELS,
9756                             'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
9757                             'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path)),
9758                     p_warning_location => 'generate_heuristics');
9759 
9760         END IF;
9761 
9762         --Load the model def, in which the constraint will be defined, and the variable.
9763 
9764         aload_model_def ( h_psnid_parentid ( l_key ));
9765         haload_object ( l_node_id, 1 );
9766 
9767         l_expr_id := TO_CHAR ( t_exp_exprnodeid ( l_index ));
9768 
9769         IF ( NOT h_exprid_childrenindex.EXISTS ( l_expr_id )) THEN
9770 
9771            --No property is specified, need to default in some cases.
9772 
9773            IF ( is_bom_node ( h_psnid_backindex ( l_key ))) THEN
9774 
9775               l_property_id := h_templates ('quantity');
9776 
9777            ELSIF ( t_exp_templateid ( j ) <> h_templates ('assign')) THEN
9778 
9779               --We don't need to default property for assign operator except for bom.
9780 
9781               IF ( h_psnid_detailedtype ( l_key ) IN ( h_psntypes ('component'), h_psntypes ('reference'), h_psntypes ('connector'))) THEN
9782 
9783                  l_property_id := h_templates('instancecount');
9784 
9785               ELSIF ( h_psnid_detailedtype ( l_key ) = h_psntypes ('optionfeature')) THEN
9786 
9787                  l_property_id := h_templates ('quantity');
9788 
9789               END IF;
9790            END IF;
9791         ELSE
9792 
9793            l_property_id := get_property_id ( h_exprid_childrenindex ( l_expr_id ));
9794 
9795         END IF;
9796 
9797         IF ( l_property_id IS NOT NULL ) THEN
9798 
9799            apply_system_property ( l_property_id, h_psnid_backindex ( l_key ), p_input_context );
9800 
9801         END IF;
9802 
9803         emit_invokevirtual ( h_heuristic_ops ( t_exp_templateid ( j )));
9804         emit_effectivity ( 'IDecisionDef', this_effective_from, this_effective_until, this_effective_usages );
9805 
9806         IF ( this_rule_class = h_ruleclasses ('default')) THEN
9807 
9808            emit_invokevirtual ('IModelDef.addDefaultDecision(IDecisionExprDef)');
9809 
9810         ELSIF ( this_rule_class = h_ruleclasses ('search')) THEN
9811 
9812            emit_invokevirtual ('IModelDef.addSearchDecision(IDecisionExprDef)');
9813 
9814         ELSE
9815            -- Heuristic operators (IncMin, DecMax, Assign, MinFirst, MaxFirst) can only be used in defaults or search decisions.  Rule ^RULE_NAME in model ^MODEL_NAME ignored.
9816            report_and_raise_rule_warning(
9817                     p_text => CZ_UTILS.GET_TEXT(
9818                             CZ_FCE_W_HEUR_ONLY_IN_DEF,
9819                             'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
9820                             'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
9821                     p_warning_location => 'generate_heuristics' );
9822 
9823         END IF;
9824 
9825         emit_pop ( 1 );
9826         x_output_context.context_type := const_context_heuristics;
9827 
9828      END generate_heuristics;
9829      ----------------------------------------------------------------------------------
9830      -- Scope: compile_constraints
9831      PROCEDURE generate_aggregatesum ( j IN PLS_INTEGER
9832                                      , p_input_context IN expression_context
9833                                      , x_output_context IN OUT NOCOPY expression_context
9834                                      ) IS
9835 
9836         l_expr_id          VARCHAR2(4000);
9837         l_index            PLS_INTEGER;
9838         l_return           PLS_INTEGER := const_no_instances;
9839 
9840         l_input_context    expression_context := p_input_context;
9841         l_output_context   expression_context;
9842 
9843         l_parameter        type_iterator_value;
9844 
9845      BEGIN
9846 
9847         l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
9848 
9849         IF ( expr_has_one_child ( l_expr_id )) THEN
9850 
9851           l_index := h_exprid_childrenindex ( l_expr_id );
9852 
9853         ELSE
9854 
9855           report_and_raise_rule_sys_warn(
9856             p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_INCOMPLETE_AGSUM ),
9857             p_warning_location => 'generate_aggregatesum');
9858 
9859         END IF;
9860 
9861         l_parameter := get_structure_node ( l_index );
9862 
9863         IF ( l_parameter.value_type IS NULL ) THEN
9864 
9865           report_and_raise_rule_sys_warn(
9866                 p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_AS_OPAND_STRUCT_N ),
9867                 p_warning_location => 'generate_aggregatesum');
9868 
9869         END IF;
9870 
9871         l_input_context.context_type := const_context_aggregatesum;
9872 /*
9873         l_expr_id := TO_CHAR ( t_exp_exprnodeid ( l_index ));
9874 
9875         IF ( h_exprid_childrenindex.EXISTS ( l_expr_id ) AND t_exp_exprtype ( h_exprid_childrenindex ( l_expr_id ) ) = h_exprtypes ('property')) THEN
9876 
9877            --User property is a special case - we need to generate the node, then push the
9878            --property value as an expression, and then call sum if necessary.
9879 
9880            l_return := generate_path ( l_parameter.ps_node_id, l_parameter.model_ref_expl_id, l_input_context, x_output_context );
9881 
9882         END IF;
9883 */
9884         generate_expression ( l_index, l_input_context, l_output_context );
9885 
9886         IF ( l_return = const_resourcesum_required ) THEN
9887 
9888            emit_invokevirtual('IPortExprDef.sum(INumExprDef)');
9889 
9890         END IF;
9891      END generate_aggregatesum;
9892      ----------------------------------------------------------------------------------
9893      -- Scope: compile_constraints
9894      FUNCTION is_operator ( j IN PLS_INTEGER, p_operator IN VARCHAR2 ) RETURN BOOLEAN IS
9895      BEGIN
9896 
9897         RETURN t_exp_exprtype ( j ) = h_exprtypes ('operator') AND t_exp_templateid ( j ) = h_templates ( p_operator );
9898 
9899      END is_operator;
9900      ----------------------------------------------------------------------------------
9901      -- Scope: compile_constraints
9902      FUNCTION is_text_selection ( j IN PLS_INTEGER ) RETURN BOOLEAN IS
9903 
9904         l_expr_id         VARCHAR2(4000);
9905         l_index           PLS_INTEGER;
9906 
9907      BEGIN
9908 
9909         IF ( t_exp_exprtype ( j ) = h_exprtypes ('argument')) THEN
9910 
9911            RETURN retrieve_parameter ( t_exp_argumentname ( j )).value_type = const_valuetype_selection;
9912 
9913         ELSE
9914 
9915            l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
9916 
9917            IF (( NOT h_exprid_childrenindex.EXISTS ( l_expr_id )) OR h_exprid_numberofchildren ( l_expr_id ) = 1 ) THEN RETURN FALSE; END IF;
9918 
9919            l_index := h_exprid_childrenindex ( l_expr_id );
9920            IF ( NVL ( t_exp_templateid ( l_index ), 0 ) = h_templates ('selection')) THEN RETURN TRUE; END IF;
9921 
9922         END IF;
9923 
9924         RETURN FALSE;
9925      END is_text_selection;
9926      ----------------------------------------------------------------------------------
9927      -- Scope: compile_constraints
9928      PROCEDURE generate_expression ( j IN PLS_INTEGER
9929                                    , p_input_context IN expression_context
9930                                    , x_output_context IN OUT NOCOPY expression_context
9931                                    ) IS
9932 
9933        --Must be local variables because of recursion.
9934 
9935        l_expr_id          VARCHAR2(4000);
9936        l_index            PLS_INTEGER;
9937        l_aux              PLS_INTEGER;
9938        l_count            PLS_INTEGER;
9939        l_key              VARCHAR2(4000);
9940 
9941        l_input_context    expression_context := p_input_context;
9942        l_output_context   expression_context;
9943 
9944        l_left_context     expression_context;
9945        l_right_context    expression_context;
9946        l_acc_init         type_varchar4000_table;
9947 
9948        l_lhs_selection    BOOLEAN;
9949        l_rhs_selection    BOOLEAN;
9950        l_side             PLS_INTEGER;
9951 
9952        l_lhs_target       NUMBER;
9953        l_rhs_target       NUMBER;
9954 
9955      BEGIN
9956 
9957        CASE t_exp_exprtype ( j )
9958 
9959          WHEN h_exprtypes ('node') THEN
9960 
9961            generate_structure_node ( j, p_input_context, x_output_context );
9962 
9963          WHEN h_exprtypes ('literal') THEN
9964 
9965            generate_literal ( j, get_literal_value ( j ), t_exp_datatype ( j ), p_input_context, x_output_context );
9966 
9967          WHEN h_exprtypes ('argument') THEN
9968 
9969            generate_parameter ( j, p_input_context, x_output_context );
9970 
9971          WHEN h_exprtypes ('operator') THEN
9972 
9973            l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
9974 
9975            IF ( l_input_context.context_type = const_context_generic ) THEN
9976 
9977               IF ( h_logical_ops.EXISTS ( t_exp_templateid ( j ))) THEN
9978 
9979                  l_input_context.context_type := const_context_logical;
9980 
9981               ELSIF ( h_numeric_ops.EXISTS ( t_exp_templateid ( j ))) THEN
9982 
9983                  l_input_context.context_type := const_context_numeric;
9984 
9985               END IF;
9986            END IF;
9987 
9988            IF ( h_operators_2.EXISTS ( t_exp_templateid ( j ))) THEN
9989 
9990               --Operators with 2 operands.
9991 
9992               IF ( expr_has_two_children ( l_expr_id )) THEN
9993 
9994                  l_index := h_exprid_childrenindex ( l_expr_id );
9995 
9996               ELSE
9997 
9998                  report_and_raise_rule_sys_warn(
9999                   p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_RE_ENODE_TWO_CHILD,
10000                           'EXPR_ID', l_expr_id ),
10001                   p_warning_location => 'generate_expression');
10002 
10003               END IF;
10004 
10005               l_aux := l_index + 1;
10006 
10007               IF ( t_exp_templateid ( j ) IN ( h_templates ('subsetof'), h_templates ('union'))) THEN
10008 
10009                  --Special validation for SubsetOf and Union operators.
10010 
10011                  l_lhs_target := 0;
10012                  l_rhs_target := 0;
10013 
10014                  IF ( t_exp_exprtype ( l_index ) = h_exprtypes ('node')) THEN
10015 
10016                     l_lhs_target := get_port_id ( TO_CHAR ( t_exp_psnodeid ( l_index )));
10017 
10018                     IF ( l_lhs_target IS NULL ) THEN
10019 
10020                        report_and_raise_rule_sys_warn (
10021                         p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_AS_PORT_LIMITS ),
10022                         p_warning_location => 'generate_expression');
10023 
10024                     END IF;
10025                  END IF;
10026 
10027                  IF ( t_exp_exprtype ( l_aux ) = h_exprtypes ('node')) THEN
10028 
10029                     l_rhs_target := get_port_id ( TO_CHAR ( t_exp_psnodeid ( l_aux )));
10030 
10031                     IF ( l_rhs_target IS NULL ) THEN
10032 
10033                        report_and_raise_rule_sys_warn (
10034                         p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_AS_PORT_LIMITS ),
10035                         p_warning_location => 'generate_expression');
10036 
10037                     END IF;
10038                  END IF;
10039 
10040                  IF ( l_lhs_target <> 0 AND l_rhs_target <> 0 AND l_lhs_target <> l_rhs_target ) THEN
10041 
10042                     report_and_raise_rule_sys_warn(
10043                     p_text => GET_NOT_TRANSLATED_TEXT(
10044                             CZ_FCE_SW_COMPARE_TXPROP_TXLIT ),
10045                     p_warning_location => 'generate_expression' );
10046 
10047                  END IF;
10048               END IF;
10049 
10050               generate_expression ( l_index, p_input_context, l_left_context );
10051               generate_expression ( l_aux, p_input_context, l_right_context );
10052 
10053               --The following line corresponds to the case of division or multiplication by 1.
10054 
10055               IF ( l_left_context.context_type = const_context_literal OR l_right_context.context_type = const_context_literal ) THEN RETURN; END IF;
10056 
10057               invoke_operator2 ( t_exp_templateid ( j ), l_aux, l_right_context );
10058 
10059            ELSIF ( h_operators_3.EXISTS ( t_exp_templateid ( j ))) THEN
10060 
10061               --n-ary operators, defined on IModelDef: AnyTrue, AllTrue, Min, Max.
10062 
10063               IF ( expr_has_children ( l_expr_id )) THEN
10064 
10065                 l_index := h_exprid_childrenindex ( l_expr_id );
10066 
10067               ELSE
10068 
10069                 report_and_raise_rule_sys_warn (
10070                       p_text => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SW_RE_ENODE_CHILDREN,
10071                                   'EXPR_ID', l_expr_id ),
10072                       p_warning_location => 'generate_expression');
10073 
10074               END IF;
10075 
10076               l_aux := h_exprid_numberofchildren ( l_expr_id );
10077 
10078               --Put all the operand expressions on the stack.
10079 
10080               FOR i IN 1..l_aux LOOP
10081 
10082                  generate_expression ( l_index, l_input_context, x_output_context );
10083                  l_index := l_index + 1;
10084 
10085               END LOOP;
10086 
10087               IF ( t_exp_templateid ( j ) IN ( h_templates ('anytrue'), h_templates ('alltrue'))) THEN
10088 
10089                   invoke_anyalltrue ( t_exp_templateid ( j ), h_exprid_numberofchildren ( l_expr_id ), t_exp_exprparentid ( j ));
10090 
10091               ELSIF ( h_exprid_numberofchildren ( l_expr_id ) > 1 ) THEN
10092 
10093                   invoke_operator3 ( t_exp_templateid ( j ), h_exprid_numberofchildren ( l_expr_id ), 'INumExprDef' );
10094 
10095               END IF;
10096 
10097               --The number of children may have been changed by a collect, need to restore.
10098 
10099               h_exprid_numberofchildren ( l_expr_id ) := l_aux;
10100 
10101            ELSIF ( h_operators_1.EXISTS ( t_exp_templateid ( j ))) THEN
10102 
10103               --Operators with 1 operand.
10104 
10105               IF ( expr_has_one_child ( l_expr_id )) THEN
10106 
10107                 generate_expression ( h_exprid_childrenindex ( l_expr_id ), p_input_context, x_output_context );
10108 
10109               ELSE
10110 
10111                 -- 'The expression node with the id-^EXPR_ID must have exactly one child. Rule ^RULE_NAME in the model ^MODEL_NAME ignored.'
10112 
10113                 report_and_raise_rule_sys_warn(
10114                   p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_RE_ENODE_ONE_CHILD,
10115                           'EXPR_ID', l_expr_id ),
10116                   p_warning_location => 'generate_expression');
10117 
10118               END IF;
10119 
10120               emit_invokevirtual ( h_operators_1 ( t_exp_templateid ( j )));
10121 
10122            ELSIF ( t_exp_templateid ( j ) = h_templates('optionsof')) THEN
10123 
10124               IF ( expr_has_one_child ( l_expr_id )) THEN
10125 
10126                  l_index := h_exprid_childrenindex ( l_expr_id );
10127 
10128               ELSE
10129 
10130                  -- 'The expression node with the id-^EXPR_ID must have exactly one child. Rule ^RULE_NAME in the model ^MODEL_NAME ignored.'
10131 
10132                  report_and_raise_rule_sys_warn(
10133                    p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_RE_ENODE_ONE_CHILD,
10134                          'EXPR_ID', l_expr_id ),
10135                    p_warning_location => 'generate_expression');
10136 
10137               END IF;
10138 
10139               IF ( logical_context ( j, p_input_context.context_type )) THEN
10140 
10141                  --This is operator OptionsOf as a child of AnyTrue/AllTrue. Emulate property Options(),
10142                  --applied to the operand.
10143 
10144                  t_exp_exprparentid ( l_index ) := t_exp_exprparentid ( j );
10145                  generate_options ( l_index, p_input_context, x_output_context );
10146 
10147               END IF;
10148 
10149            ELSIF ( t_exp_templateid ( j ) = h_templates ('aggregatesum')) THEN
10150 
10151               generate_aggregatesum ( j, p_input_context, x_output_context );
10152 
10153            ELSIF ( t_exp_templateid ( j ) = h_templates ('logic')) THEN
10154 
10155               generate_logic_template ( j, p_input_context, x_output_context );
10156 
10157            ELSIF ( t_exp_templateid ( j ) = h_templates ('comparison')) THEN
10158 
10159               generate_comparison_template ( j, p_input_context, x_output_context );
10160 
10161            ELSIF ( t_exp_templateid ( j ) = h_templates ('accumulator')) THEN
10162 
10163               generate_accumulator_template ( j, p_input_context, x_output_context );
10164 
10165            ELSIF ( t_exp_templateid ( j ) = h_templates ('propertybased')) THEN
10166 
10167               generate_compatible ( j, p_input_context, x_output_context );
10168 
10169            ELSIF ( t_exp_templateid ( j ) IN ( h_templates ('addsto'), h_templates ('subtractsfrom'))) THEN
10170 
10171               --This is an Accumulator rule.
10172 
10173               l_expr_id := TO_CHAR ( t_exp_exprnodeid ( j ));
10174 
10175               --Accumulator operator can only have two arguments.
10176 
10177               IF ( expr_has_two_children ( l_expr_id )) THEN
10178 
10179                  l_index := h_exprid_childrenindex ( l_expr_id );
10180 
10181               ELSE
10182 
10183                  report_and_raise_rule_sys_warn (
10184                   p_text => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SW_RE_ENODE_TWO_CHILD,
10185                           'EXPR_ID', l_expr_id ),
10186                   p_warning_location => 'generate_expression');
10187 
10188               END IF;
10189 
10190               --This is expression index of the target.
10191 
10192               --Need to generate the target first, because generation of contributor will depend on the
10193               --target (LCA). Cannot just generate the path here because target can be an argument, for
10194               --example, in case of FORALL operator.
10195 
10196               l_aux := l_index + 1;
10197               l_input_context.context_type := const_context_target;
10198 
10199               generate_expression ( l_aux, l_input_context, x_output_context );
10200 
10201               l_count := x_output_context.context_num_data;
10202               l_key := x_output_context.context_data;
10203 
10204               --If output context is 'target', the target didn't exist and needs to be stored.
10205               --For an existing target, the context would have been changed to 'generic' in
10206               --generate_path procedure.
10207 
10208               IF ( x_output_context.context_type = const_context_target ) THEN
10209 
10210                  astore_register ( l_key );
10211 
10212                  t_target_quantifiers ( l_count ) := t_acc_quantifiers ( l_count );
10213                  h_target_quantifiers ( l_count ) := h_acc_quantifiers ( l_count );
10214 
10215               END IF;
10216 
10217               l_input_context.context_type := const_context_contributor;
10218               l_input_context.context_num_data := l_count;
10219 
10220               t_acc_local_quantifiers.DELETE;
10221               contributor_validation := 0;
10222 
10223               generate_expression ( l_index, l_input_context, x_output_context );
10224 
10225               IF ( contributor_validation > 1 ) THEN
10226 
10227                  --The output context contains the number of the generated expression's participants
10228                  --that are under ports. This validates the following restrictions:
10229 
10230                  --If all the nodes participating in the expressions are in the mandatory closure of
10231                  --the root, there are no restrictions on the expression.
10232                  --Otherwise, we allow only one node which can be multiplied by a constant, which is
10233                  --either a literal or a value of a user property.
10234 
10235                  --A contribution expression that uses a participant which is under an instantiable
10236                  --Component or referenced Model cannot also use another participant. Rule ^RULE_NAME
10237                  --in the Model ^MODEL_NAME ignored.
10238 
10239                  report_and_raise_rule_warning(
10240                     p_text => CZ_UTILS.GET_TEXT(
10241                             CZ_FCE_W_INVALID_CONTRIB,
10242                             'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
10243                             'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path)),
10244                     p_warning_location => 'generate_expression' );
10245 
10246               END IF;
10247 
10248               IF ( t_exp_templateid ( j ) = h_templates('subtractsfrom')) THEN
10249 
10250                  emit_invokevirtual ( 'INumExprDef.neg()');
10251 
10252               END IF;
10253 
10254               combine_contributors ( l_count );
10255               x_output_context.context_type := const_context_accumulation;
10256 
10257            ELSIF ( h_heuristic_ops.EXISTS ( t_exp_templateid ( j ))) THEN
10258 
10259               --This is one of the heuristics operators: Assign, DecMax, IncMin, MinFirst or MaxFirst.
10260               --These operators can only be applied to a variable and the decision should be added to
10261               --the model def of this variable's parent.
10262 
10263               generate_heuristics ( j, p_input_context, x_output_context );
10264 
10265            ELSIF ( h_mathrounding_ops.EXISTS ( t_exp_templateid ( j ))) THEN
10266 
10267               generate_mathrounding ( j, p_input_context, x_output_context );
10268 
10269            ELSIF ( h_trigonometric_ops.EXISTS ( t_exp_templateid ( j ))) THEN
10270 
10271               generate_trigonometric ( j, p_input_context, x_output_context );
10272 
10273            ELSIF ( t_exp_templateid ( j ) IN ( h_templates('pow'), h_templates('integerpow'))) THEN
10274 
10275               generate_power ( j, p_input_context, x_output_context );
10276 
10277            ELSIF ( h_operators_2_text.EXISTS ( t_exp_templateid ( j ))) THEN
10278 
10279               --Text comparison operators.
10280 
10281               IF ( expr_has_two_children ( l_expr_id )) THEN
10282 
10283                  l_index := h_exprid_childrenindex ( l_expr_id );
10284 
10285               ELSE
10286 
10287                  report_and_raise_rule_sys_warn(
10288                   p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_RE_ENODE_TWO_CHILD,
10289                           'EXPR_ID', l_expr_id ),
10290                   p_warning_location => 'generate_expression');
10291 
10292               END IF;
10293 
10294               l_aux := l_index + 1;
10295 
10296               --Need to skip the totext operator if present.
10297 
10298               IF ( is_operator ( l_index, 'totext')) THEN
10299 
10300                 IF  ( expr_has_one_child ( TO_CHAR ( t_exp_exprnodeid ( l_index )))) THEN
10301 
10302                   l_index := h_exprid_childrenindex ( TO_CHAR ( t_exp_exprnodeid ( l_index )));
10303 
10304                 ELSE
10305 
10306                   report_and_raise_rule_sys_warn(
10307                     p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_RE_ENODE_ONE_CHILD,
10308                           'EXPR_ID',  TO_CHAR ( t_exp_exprnodeid ( l_index ))),
10309                     p_warning_location => 'generate_expression');
10310 
10311                 END IF;
10312 
10313               END IF;
10314 
10315               IF ( is_operator ( l_aux, 'totext')) THEN
10316 
10317                 IF ( expr_has_one_child ( TO_CHAR ( t_exp_exprnodeid ( l_aux )))) THEN
10318 
10319                   l_aux := h_exprid_childrenindex ( TO_CHAR ( t_exp_exprnodeid ( l_aux )));
10320 
10321                 ELSE
10322 
10323                   report_and_raise_rule_sys_warn(
10324                     p_text => GET_NOT_TRANSLATED_TEXT( CZ_FCE_SW_RE_ENODE_ONE_CHILD,
10325                             'EXPR_ID', TO_CHAR ( t_exp_exprnodeid ( l_aux ))),
10326                     p_warning_location => 'generate_expression');
10327 
10328                 END IF;
10329               END IF;
10330 
10331               l_lhs_selection := is_text_selection ( l_index );
10332               l_rhs_selection := is_text_selection ( l_aux );
10333 
10334               IF (( l_lhs_selection AND t_exp_exprtype ( l_aux ) <> h_exprtypes ('literal')) OR
10335                   ( l_rhs_selection AND t_exp_exprtype ( l_index ) <> h_exprtypes ('literal')))THEN
10336 
10337                  report_and_raise_rule_sys_warn(
10338                     CZ_UTILS.GET_TEXT(CZ_FCE_SW_COMPARE_TXPROP_TXLIT ),
10339                     'generate_expression' );
10340 
10341               END IF;
10342 
10343               l_input_context.context_type := const_context_selection;
10344 
10345               c_.combinations.DELETE;
10346               c_.participants.DELETE;
10347 
10348               o_.DELETE;
10349               s_.DELETE;
10350               t_.DELETE;
10351 
10352               l_side := 0;
10353 
10354               IF ( l_lhs_selection ) THEN l_side := 1;
10355               ELSIF ( l_rhs_selection ) THEN l_side := 2; END IF;
10356 
10357               generate_expression ( l_index, l_input_context, l_output_context );
10358               generate_expression ( l_aux, l_input_context, l_output_context );
10359 
10360               --All the data necessary for generation are already in the corresponding data structures.
10361 
10362               generate_text_comparison ( t_exp_templateid ( j ), l_side, p_input_context, x_output_context );
10363 
10364            ELSIF ( t_exp_templateid ( j ) = h_templates('none')) THEN
10365 
10366               RETURN;
10367 
10368            ELSE
10369 
10370               --#<should never happen>
10371               -- 'Unknown operator type "^OPERTYPE" in the rule. Rule "^RULE_NAME" in the Model ^MODEL_NAME" ignored.';
10372               report_and_raise_rule_sys_warn(
10373                 GET_NOT_TRANSLATED_TEXT(CZ_FCE_SW_UNKNOWN_OP_TYPE,
10374                   'OPERTYPE',  TO_CHAR(t_exp_templateid ( j ))),
10375                 'generate_expression'
10376                );
10377 
10378            END IF;
10379 
10380          WHEN h_exprtypes ('forall') THEN
10381 
10382            generate_statement_forall ( j, p_input_context, x_output_context );
10383 
10384          WHEN h_exprtypes ('compatible') THEN
10385 
10386            generate_compatible ( j, p_input_context, x_output_context );
10387 
10388          WHEN h_exprtypes ('constant') THEN
10389 
10390            generate_constant ( j );
10391 
10392          ELSE
10393 
10394            --#<should never happen>
10395            report_and_raise_rule_sys_warn(
10396                 CZ_UTILS.GET_TEXT('CZ_E_UNKNOWN_EXPR_TYPE',
10397                   'RULENAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name)),
10398                 'generate_expression'
10399                );
10400 
10401        END CASE;
10402      END generate_expression;
10403      ----------------------------------------------------------------------------------
10404      PROCEDURE resolve_node ( p_relative_node_path IN VARCHAR2
10405                             , p_parent_node_id     IN NUMBER
10406                             , p_parent_expl_id     IN NUMBER
10407                             , x_child_node_id      IN OUT NOCOPY NUMBER
10408                             , x_child_expl_id      IN OUT NOCOPY NUMBER
10409                             ) IS
10410 
10411        l_eff_from            DATE := const_epoch_begin;
10412        l_eff_until           DATE := const_epoch_end;
10413        l_index               PLS_INTEGER;
10414        l_parent_id           NUMBER;
10415 
10416        l_path_tbl            type_number_table;
10417        l_node_tbl            type_varchar4000_table;
10418        l_counter             NUMBER;
10419 
10420        l_return_node_id_tbl  type_number_table;
10421        l_return_expl_id_tbl  type_number_table;
10422 
10423      ----------------------------------------------------------------------------------
10424        PROCEDURE resolve_children ( p_index      IN PLS_INTEGER
10425                                   , p_node_id    IN NUMBER
10426                                   , p_expl_id    IN NUMBER
10427                                   , p_eff_from   IN DATE
10428                                   , p_eff_until  IN DATE
10429                                   ) IS
10430 
10431          t_eff_from_tbl   type_date_table;
10432          t_eff_until_tbl  type_date_table;
10433          t_node_id_tbl    type_number_table;
10434          t_expl_id_tbl    type_number_table;
10435 
10436          l_eff_from_tbl   type_date_table;
10437          l_eff_until_tbl  type_date_table;
10438          l_node_id_tbl    type_number_table;
10439          l_expl_id_tbl    type_number_table;
10440          l_path_tbl       type_number_table;
10441 
10442          l_counter        PLS_INTEGER := 0;
10443          l_index          PLS_INTEGER;
10444 
10445        BEGIN
10446 
10447          SELECT ps_node_id, model_ref_expl_id, effective_from, effective_until
10448            BULK COLLECT INTO l_node_id_tbl, l_expl_id_tbl, l_eff_from_tbl, l_eff_until_tbl
10449            FROM cz_explmodel_nodes_v
10450           WHERE model_id = p_component_id
10451             AND parent_psnode_expl_id = p_expl_id
10452             AND effective_parent_id = p_node_id
10453             AND suppress_flag = '0'
10454             AND name = l_node_tbl ( p_index );
10455 
10456          FOR i IN 1..l_node_id_tbl.COUNT LOOP
10457 
10458            IF ( p_eff_from > l_eff_from_tbl ( i )) THEN l_eff_from_tbl ( i ) := p_eff_from; END IF;
10459            IF ( p_eff_until < l_eff_until_tbl ( i )) THEN l_eff_until_tbl ( i ) := p_eff_until; END IF;
10460 
10461            IF( l_eff_from_tbl ( i ) <= l_eff_until_tbl ( i )) THEN
10462 
10463              l_counter := l_counter + 1;
10464 
10465              t_eff_from_tbl ( l_counter ) := l_eff_from_tbl ( i );
10466              t_eff_until_tbl ( l_counter ) := l_eff_until_tbl ( i );
10467              t_node_id_tbl ( l_counter ) := l_node_id_tbl ( i );
10468              t_expl_id_tbl ( l_counter ) := l_expl_id_tbl ( i );
10469 
10470            END IF;
10471          END LOOP;
10472 
10473          FOR i IN 1..t_node_id_tbl.COUNT LOOP
10474 
10475            IF( p_index = l_node_tbl.COUNT )THEN
10476 
10477              l_index := l_return_node_id_tbl.COUNT + 1;
10478 
10479              l_return_node_id_tbl ( l_index ) := t_node_id_tbl ( i );
10480              l_return_expl_id_tbl ( l_index ) := t_expl_id_tbl ( i );
10481 
10482            ELSE
10483 
10484              resolve_children ( p_index + 1, t_node_id_tbl ( i ), t_expl_id_tbl ( i ), t_eff_from_tbl ( i ), t_eff_until_tbl ( i ));
10485 
10486            END IF;
10487          END LOOP;
10488        END resolve_children;
10489      ----------------------------------------------------------------------------------
10490      BEGIN
10491 
10492         l_node_tbl := split_str_path ( p_relative_node_path );
10493         l_path_tbl := build_reference_path ( p_parent_expl_id );
10494 
10495         --Propagate effectivity from all the bom references down from the root model.
10496 
10497         FOR i IN 1..l_path_tbl.COUNT LOOP
10498 
10499           --We need to stop on the model, in which the rule is defined.
10500 
10501           IF ( l_path_tbl ( i ) = p_component_id ) THEN EXIT; END IF;
10502 
10503             --Account only for references to bom(s).
10504 
10505             l_index := h_psnid_backindex ( l_path_tbl ( i ));
10506 
10507             IF ( is_bom_port ( l_index )) THEN
10508 
10509                IF ( t_psn_effectivefrom ( l_index ) > l_eff_from ) THEN l_eff_from := t_psn_effectivefrom ( l_index ); END IF;
10510                IF ( t_psn_effectiveuntil ( l_index ) < l_eff_until ) THEN l_eff_until := t_psn_effectiveuntil ( l_index ); END IF;
10511 
10512             END IF;
10513         END LOOP;
10514 
10515         --Adjust effectivities for the least unambiguous parent.
10516 
10517         l_index := h_psnid_backindex(p_parent_node_id);
10518 
10519         IF ( t_psn_effectivefrom ( l_index ) > l_eff_from ) THEN l_eff_from := t_psn_effectivefrom ( l_index ); END IF;
10520         IF ( t_psn_effectiveuntil ( l_index ) < l_eff_until ) THEN l_eff_until := t_psn_effectiveuntil ( l_index ); END IF;
10521 
10522         --Finally adjust for the rule effectivity.
10523 
10524         IF( this_effective_from > l_eff_from)THEN l_eff_from := this_effective_from; END IF;
10525         IF( this_effective_until < l_eff_until)THEN l_eff_until := this_effective_until; END IF;
10526 
10527         --If effectivity range is empty, it will be impossible to resolve the node.
10528 
10529         IF( l_eff_until < l_eff_from )THEN
10530           -- The reference ^NODE_NAME is invalid. At least one node does not exist in the Model or is not effective when the rule is effective. Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
10531           report_and_raise_rule_warning (
10532              CZ_UTILS.GET_TEXT ( CZ_FCE_W_INCORRECT_REFERENCE,
10533                'NODE_NAME', REPLACE (p_relative_node_path, FND_GLOBAL.LOCAL_CHR(7), '.'),
10534                'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH( p_component_id, p_model_path ),
10535                'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name )),
10536              'RESOLVE_CHILDREN'
10537             );
10538         END IF;
10539 
10540         IF( l_node_tbl.COUNT = 0 )THEN
10541 
10542           x_child_node_id := p_parent_node_id;
10543           x_child_expl_id := p_parent_expl_id;
10544           RETURN;
10545 
10546         END IF;
10547 
10548         resolve_children ( 1, p_parent_node_id, p_parent_expl_id, l_eff_from, l_eff_until );
10549 
10550         IF ( l_return_node_id_tbl.COUNT = 0 ) THEN
10551           -- The reference ^NODE_NAME is invalid. At least one node does not exist in the Model or is not effective when the rule is effective. Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
10552           report_and_raise_rule_warning (
10553              CZ_UTILS.GET_TEXT ( CZ_FCE_W_INCORRECT_REFERENCE,
10554                'NODE_NAME', REPLACE (p_relative_node_path, FND_GLOBAL.LOCAL_CHR(7), '.'),
10555                'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH ( p_component_id, p_model_path ),
10556                'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name )),
10557              'RESOLVE_CHILDREN'
10558             );
10559 
10560         ELSIF ( l_return_node_id_tbl.COUNT > 1 ) THEN
10561           -- Unable to resolve Model node reference ^NODE_NAME because it is ambiguous. Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
10562           report_and_raise_rule_warning (
10563              CZ_UTILS.GET_TEXT ( CZ_FCE_W_AMBIGUOUS_REFERENCE,
10564                'NODE_NAME', REPLACE (p_relative_node_path, FND_GLOBAL.LOCAL_CHR(7), '.'),
10565                'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH ( p_component_id, p_model_path ),
10566                'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name )),
10567              'RESOLVE_CHILDREN'
10568             );
10569 
10570         ELSE
10571 
10572           x_child_node_id := l_return_node_id_tbl ( 1 );
10573           x_child_expl_id := l_return_expl_id_tbl ( 1 );
10574 
10575         END IF;
10576    END resolve_node;
10577  ---------------------------------------------------------------------------------------
10578    BEGIN --> compile_constraints
10579 
10580      free_registers ();
10581 
10582      SELECT model_ref_expl_id, parent_expl_node_id, component_id, referring_node_id, expl_node_type
10583        BULK COLLECT INTO t_expl_modelrefexplid, t_expl_parentexplnodeid, t_expl_componentid,
10584                          t_expl_referringnodeid, t_expl_explnodetype
10585        FROM cz_model_ref_expls
10586       WHERE model_id = p_component_id
10587         AND deleted_flag = '0';
10588 
10589      FOR i IN 1..t_expl_modelrefexplid.COUNT LOOP
10590 
10591        h_explid_backindex ( TO_CHAR ( t_expl_modelrefexplid ( i ))) := i;
10592 
10593        IF ( t_expl_referringnodeid ( i ) IS NOT NULL ) THEN
10594 
10595           h_parentid_referring_explid ( TO_CHAR ( t_expl_parentexplnodeid ( i )))( TO_CHAR ( t_expl_referringnodeid ( i ))) := t_expl_modelrefexplid ( i );
10596 
10597        END IF;
10598      END LOOP;
10599 
10600      FOR rule IN ( SELECT rule_id, rule_type, name, reason_id, rule_folder_id, component_id, model_ref_expl_id,
10601                          effective_from, effective_until, effective_usage_mask, effectivity_set_id, invalid_flag,
10602                          unsatisfied_msg_id, unsatisfied_msg_source, presentation_flag, rule_class, class_name
10603                      FROM cz_rules
10604                     WHERE devl_project_id = p_component_id
10605                       AND deleted_flag = '0'
10606                       AND disabled_flag = '0'
10607                     ORDER BY class_seq ) LOOP
10608      BEGIN
10609 
10610         this_rule_id := rule.rule_id;
10611         this_reason_id := rule.reason_id;
10612         this_rule_class := rule.rule_class;
10613         this_rule_name := rule.name;
10614         this_effective_from := NVL ( rule.effective_from, const_epoch_begin );
10615         this_effective_until := NVL ( rule.effective_until, const_epoch_end );
10616         this_effective_usages := LPAD ( rule.effective_usage_mask, 16, '0' );
10617 
10618         set_rule_savepoint ();
10619 
10620         IF ( rule.invalid_flag = '1' ) THEN
10621            IF ( rule.presentation_flag = '0' ) THEN
10622               -- Parsing errors found. Fix parsing errors. Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
10623               report_and_raise_rule_warning(
10624                      p_text => CZ_UTILS.GET_TEXT (
10625                                CZ_FCE_W_PARSE_FAILED,
10626                                'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name ),
10627                                'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path)
10628                                ),
10629                      p_warning_location => 'compile_constraints' );
10630 
10631            ELSE
10632 
10633               report_and_raise_rule_warning(
10634                      -- Invalid or incomplete rule, please check the rule. Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
10635                      p_text => CZ_UTILS.GET_TEXT (
10636                                CZ_FCE_W_TEMPLATE_INVALID,
10637                                'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name ),
10638                                'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path)),
10639                      p_warning_location => 'compile_constraints' );
10640 
10641            END IF;
10642         END IF;
10643 
10644         IF ( rule.effectivity_set_id IS NOT NULL ) THEN
10645            IF ( NOT h_effsetid_effectivefrom.EXISTS ( TO_CHAR ( rule.effectivity_set_id ))) THEN
10646 
10647               report_and_raise_rule_sys_warn (
10648                   p_text => GET_NOT_TRANSLATED_TEXT (
10649                             CZ_FCE_SW_RULEINCORRECTEFFSET,
10650                             'RULE_NAME',
10651                             CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name ),
10652                             'MODEL_NAME',
10653                             CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH (p_component_id, p_model_path )),
10654                   p_warning_location => 'compile_constraints');
10655 
10656            ELSE
10657 
10658               this_effective_from := h_effsetid_effectivefrom ( TO_CHAR ( rule.effectivity_set_id ));
10659               this_effective_until := h_effsetid_effectiveuntil ( TO_CHAR ( rule.effectivity_set_id ));
10660 
10661            END IF;
10662         END IF;
10663 
10664         t_exp_modelrefexplid.DELETE;
10665         t_exp_exprtype.DELETE;
10666         t_exp_exprnodeid.DELETE;
10667         t_exp_exprparentid.DELETE;
10668         t_exp_templateid.DELETE;
10669         t_exp_psnodeid.DELETE;
10670         t_exp_datavalue.DELETE;
10671         t_exp_propertyid.DELETE;
10672         t_exp_paramindex.DELETE;
10673         t_exp_argumentindex.DELETE;
10674         t_exp_argumentname.DELETE;
10675         t_exp_datatype.DELETE;
10676         t_exp_datanumvalue.DELETE;
10677         t_exp_paramsignatureid.DELETE;
10678         t_exp_relativenodepath.DELETE;
10679         t_exp_seqnbr.DELETE;
10680 
10681         h_exprid_childrenindex.DELETE;
10682         h_exprid_numberofchildren.DELETE;
10683         h_exprid_backindex.DELETE;
10684 
10685         IF ( rule.rule_type = h_ruletypes ('statement')) THEN
10686 
10687           SELECT model_ref_expl_id, expr_type, expr_node_id, expr_parent_id, template_id, ps_node_id, data_value,
10688                  property_id, param_index, argument_index, argument_name, data_type, data_num_value,
10689                  param_signature_id, relative_node_path, seq_nbr
10690             BULK COLLECT INTO t_exp_modelrefexplid, t_exp_exprtype, t_exp_exprnodeid, t_exp_exprparentid,
10691                               t_exp_templateid, t_exp_psnodeid, t_exp_datavalue, t_exp_propertyid,
10692                               t_exp_paramindex, t_exp_argumentindex, t_exp_argumentname, t_exp_datatype,
10693                               t_exp_datanumvalue, t_exp_paramsignatureid, t_exp_relativenodepath, t_exp_seqnbr
10694             FROM cz_expression_nodes
10695            WHERE rule_id = rule.rule_id
10696              AND expr_type <> h_exprtypes ('punctuation')
10697              AND deleted_flag = '0'
10698            ORDER BY expr_parent_id, seq_nbr;
10699 
10700           l_rule_expr_lastindex := t_exp_exprnodeid.COUNT;
10701 
10702           IF ( l_rule_expr_lastindex = 0 ) THEN
10703              -- Rule definition is empty.  Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
10704              report_and_raise_rule_warning(
10705                   p_text => CZ_UTILS.GET_TEXT(
10706                             CZ_FCE_W_EMPTY_RULE,
10707                             'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH(this_rule_id, this_rule_name),
10708                             'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH(p_component_id, p_model_path) ),
10709                     p_warning_location => 'compile_constraints' );
10710 
10711           END IF;
10712 
10713           FOR i IN 1..l_rule_expr_lastindex LOOP
10714 
10715             IF ( t_exp_exprparentid ( i ) IS NOT NULL ) THEN
10716 
10717               l_key := TO_CHAR ( t_exp_exprparentid ( i ));
10718 
10719               IF( h_exprid_numberofchildren.EXISTS ( l_key ))THEN
10720 
10721                 h_exprid_numberofchildren ( l_key ) := h_exprid_numberofchildren ( l_key ) + 1;
10722 
10723               ELSE
10724 
10725                 h_exprid_numberofchildren ( l_key ) := 1;
10726 
10727               END IF;
10728 
10729               IF ( NOT h_exprid_childrenindex.EXISTS ( l_key ))THEN
10730 
10731                 h_exprid_childrenindex ( l_key ) := i;
10732 
10733               END IF;
10734             END IF;
10735 
10736             --Sanity check on basic expression node types. May be moved from here to the first pass
10737             --over rules (when implemented).
10738 
10739             CASE t_exp_exprtype ( i )
10740 
10741                 WHEN h_exprtypes ('node') THEN
10742 
10743                    IF ( t_exp_psnodeid ( i ) IS NULL OR t_exp_modelrefexplid ( i ) IS NULL ) THEN
10744 
10745                       report_and_raise_rule_sys_warn (
10746                         p_text => GET_NOT_TRANSLATED_TEXT (
10747                                 CZ_FCE_SW_UNDEFINED_STRUC_NODE ),
10748                         p_warning_location => 'compile_constraints');
10749 
10750                    ELSIF ( NOT h_explid_backindex.EXISTS ( TO_CHAR ( t_exp_modelrefexplid ( i )))) THEN
10751 
10752                       -- Rule participant ^NODE_NAME is not accessible. May be its model reference has been deleted.
10753 
10754                       report_and_raise_rule_warning (
10755                         p_text => CZ_UTILS.GET_TEXT (
10756                                 CZ_FCE_W_NODE_NOT_FOUND,
10757                                 'NODE_NAME', CZ_FCE_COMPILE_UTILS.GET_NODE_PATH ( t_exp_psnodeid ( i ),
10758                                    ps_node_id_table_to_string ( build_model_path ( t_exp_psnodeid ( i )))),
10759                                 'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name ),
10760                                 'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH ( p_component_id, p_model_path )),
10761                         p_warning_location => 'compile_constraints');
10762 
10763                    ELSIF ( NOT h_psnid_backindex.EXISTS ( TO_CHAR ( t_exp_psnodeid ( i )))) THEN
10764 
10765                       report_and_raise_rule_warning (
10766                         p_text => CZ_UTILS.GET_TEXT (
10767                                 CZ_FCE_W_NODE_DELETED,
10768                                 'NODE_NAME', CZ_FCE_COMPILE_UTILS.GET_NODE_PATH ( t_exp_psnodeid ( i ),
10769                                    ps_node_id_table_to_string ( build_model_path ( t_exp_psnodeid ( i )))),
10770                                 'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH( this_rule_id, this_rule_name ),
10771                                 'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH ( p_component_id, p_model_path )),
10772                         p_warning_location => 'compile_constraints');
10773 
10774                    END IF;
10775 
10776                 WHEN h_exprtypes ('property') THEN
10777 
10778                    IF ( t_exp_propertyid ( i ) IS NULL ) THEN
10779                       --  The rule is incomplete because a property is undefined. Rule ^RULE_NAME in the Model ^MODEL_NAME ignored.
10780                       report_and_raise_rule_warning (
10781                         p_text => CZ_UTILS.GET_TEXT (
10782                                 CZ_FCE_W_UNDEFINED_PROPERTY,
10783                                 'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name ),
10784                                 'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH ( p_component_id, p_model_path )),
10785                         p_warning_location => 'compile_constraints');
10786 
10787                    END IF;
10788 
10789                 WHEN h_exprtypes ('systemproperty') THEN
10790 
10791                    IF ( t_exp_templateid ( i ) IS NULL ) THEN
10792 
10793                       report_and_raise_rule_sys_warn(
10794                         p_text => GET_NOT_TRANSLATED_TEXT(
10795                                 CZ_FCE_SW_UNDEFINED_SYS_PROP ),
10796                         p_warning_location => 'compile_constraints' );
10797 
10798                    END IF;
10799 
10800                 WHEN h_exprtypes ('operator') THEN
10801 
10802                    IF ( t_exp_templateid ( i ) IS NULL ) THEN
10803 
10804                       report_and_raise_rule_sys_warn(
10805                         p_text => GET_NOT_TRANSLATED_TEXT(
10806                                 CZ_FCE_SW_UNDEFINED_OPERATOR ),
10807                         p_warning_location => 'compile_constraints' );
10808 
10809                    END IF;
10810 
10811                 WHEN h_exprtypes ('template') THEN
10812 
10813                    IF ( t_exp_templateid ( i ) IS NULL ) THEN
10814 
10815                       report_and_raise_rule_sys_warn(
10816                         p_text => GET_NOT_TRANSLATED_TEXT(
10817                                 CZ_FCE_SW_UNDEFINED_OP_TEMPL ),
10818                         p_warning_location => 'compile_constraints' );
10819 
10820                    END IF;
10821 
10822                 WHEN h_exprtypes ('operatorbyname') THEN
10823 
10824                    IF ( t_exp_argumentname ( i ) IS NULL ) THEN
10825 
10826                       report_and_raise_rule_sys_warn(
10827                         p_text => GET_NOT_TRANSLATED_TEXT(
10828                                 CZ_FCE_SW_UNDEFINED_OP_BY_NAME ),
10829                         p_warning_location => 'compile_constraints' );
10830 
10831                    END IF;
10832 
10833                 WHEN h_exprtypes ('nodebyname') THEN
10834 
10835                    resolve_node ( p_relative_node_path => t_exp_relativenodepath ( i )
10836                                 , p_parent_node_id     => t_exp_psnodeid ( i )
10837                                 , p_parent_expl_id     => t_exp_modelrefexplid ( i )
10838                                 , x_child_node_id      => t_exp_psnodeid ( i )
10839                                 , x_child_expl_id      => t_exp_modelrefexplid ( i )
10840                                 );
10841 
10842                    t_exp_exprtype ( i ) := h_exprtypes ('node');
10843 
10844                 ELSE NULL;
10845             END CASE;
10846 
10847             h_exprid_backindex ( TO_CHAR ( t_exp_exprnodeid ( i ))) := i;
10848 
10849           END LOOP;
10850 
10851           FOR i IN 1..l_rule_expr_lastindex LOOP
10852 
10853             --One statement rule can contain several constraints. Right now, if there is a problem
10854             --in any of these constraints, the whole rule will be ignored. This is why it is ok to
10855             --set the savepoint for the whole rule at the beginning. If we want to ignore specific
10856             --constraint within a rule we need to set and restore savepoints inside this loop.
10857 
10858             IF ( t_exp_exprparentid ( i ) IS NULL ) THEN
10859 
10860               comment ( 'Create rule: "' || this_rule_name || '" (rule_id = ' || this_rule_id || ')');
10861 
10862               --These arrays are per constraint.
10863 
10864               h_instancequantifiers.DELETE;
10865               t_instancequantifiers.DELETE;
10866               h_parameter_stack.DELETE;
10867 
10868               --All assistant variables by definition are used only within a constraint.
10869 
10870               assistant_var_id := 0;
10871 
10872               --Put the ModelDef on the stack for the last addConstraint call.
10873 
10874               aload_model_def ( p_component_id );
10875 
10876               l_output_context.context_type := const_context_generic;
10877               l_input_context.context_type := const_context_generic;
10878 
10879               generate_expression ( i, l_input_context, l_output_context );
10880 
10881               IF ( l_output_context.context_type NOT IN ( const_context_accumulation
10882                                                         , const_context_forall
10883                                                         , const_context_compatible
10884                                                         , const_context_heuristics
10885                                                         )) THEN
10886 
10887                 set_reason_id ();
10888                 add_constraint ();
10889 
10890               ELSE
10891 
10892                 --In case of accumulator rule, we need to remove the model def, put on the stack
10893                 --before expression generation, as we did not add the constraint yet.
10894                 --In the case of ForAll all the constraints are already added so we also need to
10895                 --remove the model def.
10896 
10897                 emit_pop ( 1 );
10898 
10899               END IF;
10900             END IF;
10901           END LOOP;
10902 
10903         ELSIF ( rule.rule_type = h_ruletypes ('explicitcompat')) THEN
10904 
10905           --Instance quantifiers are initialized inside the procedure as necessary.
10906 
10907           generate_explicit_compat ( l_input_context, l_output_context );
10908 
10909         ELSIF ( rule.rule_type = h_ruletypes ('designchart')) THEN
10910 
10911           --Instance quantifiers are initialized inside the procedure as necessary.
10912 
10913           generate_design_chart ( l_input_context, l_output_context );
10914 
10915         ELSIF ( rule.rule_type = h_ruletypes ('companion')) THEN
10916 
10917           l_run_id := x_run_id;
10918           CZ_DEVELOPER_UTILS_PVT.verify_special_rule( this_rule_id, this_rule_name, l_run_id );
10919 
10920         END IF; --> rule type
10921 
10922      EXCEPTION --> compile_constraints block
10923        WHEN CZ_LOGICGEN_WARNING THEN
10924           restore_rule_savepoint ();
10925        WHEN CZ_LOGICGEN_SYS_WARNING THEN
10926           restore_rule_savepoint ();
10927        WHEN CZ_LOGICGEN_ERROR THEN
10928           RAISE;
10929        WHEN CZ_LOGICGEN_SYS_ERROR THEN
10930           RAISE;
10931        WHEN OTHERS THEN
10932           report_and_raise_sys_error (
10933             p_message => GET_NOT_TRANSLATED_TEXT ( CZ_FCE_SE_UNKNOWN_IN_RULE,
10934               'RULE_NAME', CZ_FCE_COMPILE_UTILS.GET_RULE_PATH ( this_rule_id, this_rule_name )),
10935             p_run_id => x_run_id,
10936             p_model_id => p_component_id,
10937             p_error_stack => DBMS_UTILITY.FORMAT_ERROR_STACK || ' Error backtrace: ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE
10938           );
10939      END;
10940      END LOOP;
10941 
10942      --Now handle all the accumulator rules, defined in the model, if any.
10943      --Accumulator rules can only be constraints.
10944 
10945      IF ( t_acc_targets.COUNT > 0 ) THEN
10946 
10947         --Target is not just a node but includes some of the properties that can be applied, for example,
10948         --MinInstances()/MaxInstances(), applied to the same target component, will be different targets.
10949 
10950         FOR i IN 1..t_acc_targets.COUNT LOOP
10951 
10952            FOR j IN 1..t_acc_contributors ( i ).COUNT LOOP
10953 
10954               --We need to skip dummy contribution records that may have been created when combining
10955               --effectivity intervals.
10956 
10957               IF ( t_acc_contributors ( i )( j ).interval_key IS NOT NULL ) THEN
10958 
10959                  --Model def for addConstraint method.
10960 
10961                  aload_model_def ( p_component_id );
10962 
10963                  l_count := t_acc_contributors ( i )( j ).quantifiers.COUNT;
10964 
10965                  IF ( l_count > 0 ) THEN
10966 
10967                     --Will need another model def for the ForAll.
10968 
10969                     emit_dup ();
10970 
10971                     FOR jj IN 1..l_count LOOP
10972 
10973                       aload_register ( t_acc_contributors ( i )( j ).quantifiers ( jj ));
10974 
10975                     END LOOP;
10976 
10977                     IF ( l_count > 2 ) THEN
10978 
10979                       create_array ( l_count, h_javatypes ('IInstanceQuantifier'));
10980                       populate_array ( l_count );
10981 
10982                     END IF;
10983                  END IF;
10984 
10985                  aload_register ( t_acc_targets ( i ));
10986                  aload_register ( t_acc_contributors ( i )( j ).interval_key );
10987                  emit_invokevirtual('INumExprDef.eq(INumExprDef)');
10988 
10989                  --Set the violation message to the generic seeded message.
10990 
10991                  emit_dup ();
10992 
10993                  push_long_constant ( const_textid_resultnotvalid );
10994                  emit_invokevirtual('IExprDef.setId(long)');
10995 
10996                  --Remove the null object from stack after a void method.
10997 
10998                  emit_pop ( 1 );
10999                  emit_effectivity ( 'ILogicExprDef', t_acc_contributors ( i )( j ).effective_from, t_acc_contributors ( i )( j ).effective_until, t_acc_contributors ( i )( j ).effective_usage_mask );
11000 
11001                  IF ( l_count > 0 ) THEN
11002 
11003                     emit_invokevirtual ( CASE l_count
11004                                          WHEN 1 THEN 'IModelDef.forAll(IInstanceQuantifier, ILogicExprDef)'
11005                                          WHEN 2 THEN 'IModelDef.forAll(IInstanceQuantifier, IInstanceQuantifier, ILogicExprDef)'
11006                                          ELSE 'IModelDef.forAll(IInstanceQuantifier[], ILogicExprDef)'
11007                                          END );
11008 
11009                     emit_invokevirtual('IModelDef.addConstraint(IForAllDef)');
11010 
11011                  ELSE
11012 
11013                     emit_invokevirtual('IModelDef.addConstraint(ILogicExprDef)');
11014 
11015                  END IF;
11016 
11017                  emit_pop ( 1 );
11018 
11019               END IF;
11020            END LOOP;
11021         END LOOP;
11022      END IF;
11023    END compile_constraints;
11024 ---------------------------------------------------------------------------------------
11025   BEGIN --> compile_logic_file
11026 
11027      init_logic_file ();
11028      h_devlid_modelvisited ( TO_CHAR ( p_component_id )) := 1;
11029 
11030      ----------------------------------------------------------------------------------
11031      CASE p_type WHEN const_logicfile_def THEN
11032      ----------------------------------------------------------------------------------
11033      LOOP
11034 
11035         v_index := v_index + 1;
11036 
11037         CASE t_psn_psnodetype(v_index)
11038 
11039             WHEN h_psntypes('component') THEN --> component
11040 
11041                emit_model_def (v_index);
11042 
11043             WHEN h_psntypes('feature') THEN --> feature
11044 
11045                CASE t_psn_featuretype ( v_index )
11046 
11047                   WHEN h_psntypes ('booleanfeature') THEN
11048 
11049                        emit_logicvar ( v_index );
11050 
11051                   WHEN h_psntypes ('integerfeature') THEN
11052 
11053                        emit_intvar ( v_index
11054                                    , NVL ( t_psn_minimum ( v_index ), cz_fce_compile_utils.const_min_integer )
11055                                    , NVL ( t_psn_maximum ( v_index ), cz_fce_compile_utils.const_max_integer )
11056                                    );
11057 
11058                   WHEN h_psntypes ('decimalfeature') THEN
11059 
11060                        emit_floatvar ( v_index
11061                                      , NVL ( t_psn_minimum ( v_index ), const_min_double )
11062                                      , NVL ( t_psn_maximum ( v_index ), const_max_double )
11063                                      );
11064 
11065                   WHEN h_psntypes ('optionfeature') THEN
11066 
11067                        --Code will be generated when the last option is reached. Here just initialize the option count
11068                        --and store the feature index.
11069 
11070                        l_feature_idx := v_index;
11071                        l_var_min := NVL ( t_psn_minimum ( v_index ), 0 );
11072 
11073                        IF ( h_psnid_numberofchildren ( TO_CHAR ( t_psn_psnodeid ( v_index ))) > 0 ) THEN
11074 
11075                           l_option_count := h_psnid_numberofchildren ( TO_CHAR ( t_psn_psnodeid ( v_index )));
11076 
11077                        ELSE
11078 
11079                           IF ( l_var_min > 0 ) THEN
11080                              -- Invalid problem definition: Option Feature with minimum quantity greater than 0 must have children. The Option Feature is ^NODE_NAME in the Model ^MODEL_NAME.
11081                              report_and_raise_error(
11082                                   p_message => CZ_UTILS.GET_TEXT ( CZ_FCE_E_OPTION_MAXQ_NO_CHILD,
11083                                       'NODE_NAME', CZ_FCE_COMPILE_UTILS.GET_NODE_PATH(t_psn_psnodeid ( v_index ),
11084                                         ps_node_id_table_to_string(
11085                                           build_model_path(t_psn_psnodeid ( v_index ) ) ) ),
11086                                       'MODEL_NAME', CZ_FCE_COMPILE_UTILS.GET_MODEL_PATH( p_component_id, p_model_path) ),
11087                                   p_run_id => x_run_id,
11088                                   p_model_id => p_component_id
11089                              );
11090 
11091                           END IF;
11092 
11093                           l_option_count := 0;
11094 
11095                        END IF;
11096 
11097                        l_var_max := NVL ( t_psn_maximum ( v_index ), l_option_count );
11098                        l_var_count := NVL ( t_psn_maxqtyperoption ( v_index ), 1 );
11099 
11100                        --This procedure puts the first two parameters to the feature's method on the stack.
11101 
11102                        prepare_feature ( v_index );
11103 
11104                        IF ( l_option_count = 0 ) THEN
11105 
11106                           --This is a valid feature with no options, need to create the variable here.
11107 
11108                           create_feature ( v_index, l_option_count, l_var_min, l_var_max, l_var_count );
11109 
11110                        END IF;
11111 
11112                   ELSE NULL;
11113 
11114                END CASE;
11115 
11116             WHEN h_psntypes('option') THEN --> option
11117 
11118                push_variable_name ( v_index );
11119 
11120                IF ( v_index = h_psnid_lastchildindex ( TO_CHAR ( t_psn_parentid ( v_index )))) THEN
11121 
11122                   --This is the last option of the feature, create the feature after that.
11123 
11124                   create_feature ( l_feature_idx, l_option_count, l_var_min, l_var_max, l_var_count );
11125 
11126                END IF;
11127 
11128             WHEN h_psntypes('total') THEN --> total
11129 
11130                        emit_floatvar ( v_index
11131                                      , NVL ( t_psn_minimum ( v_index ), const_min_double )
11132                                      , NVL ( t_psn_maximum ( v_index ), const_max_double )
11133                                      );
11134 
11135             WHEN h_psntypes('resource') THEN --> resource
11136 
11137                        emit_floatvar ( v_index
11138                                      , NVL ( t_psn_minimum ( v_index ), 0 )
11139                                      , NVL ( t_psn_maximum ( v_index ), const_max_double )
11140                                      );
11141 
11142             WHEN h_psntypes('integertotal') THEN --> integer total
11143 
11144                        emit_intvar ( v_index
11145                                    , NVL ( t_psn_minimum ( v_index ), cz_fce_compile_utils.const_min_integer )
11146                                    , NVL ( t_psn_maximum ( v_index ), cz_fce_compile_utils.const_max_integer )
11147                                    );
11148 
11149             WHEN h_psntypes('integerresource') THEN --> integer resource
11150 
11151                        emit_intvar ( v_index
11152                                    , NVL ( t_psn_minimum ( v_index ), 0 )
11153                                    , NVL ( t_psn_maximum ( v_index ), cz_fce_compile_utils.const_max_integer )
11154                                    );
11155 
11156             WHEN h_psntypes('bommodel') THEN --> bom model
11157 
11158                emit_bommodel_def ( v_index, NVL ( t_psn_decimalqtyflag( v_index ), '0' ));
11159 
11160                --Bug #6613028. If the bom model is not root, need to create a variable here.
11161 
11162                --This is the same code as for a bom reference in the port file generation, except for
11163                --using ps_node_id instead of reference_id.
11164 
11165                IF ( t_psn_parentid ( v_index ) IS NOT NULL ) THEN
11166 
11167                   --See Section 23.13.2 'BOM Instantiatibility and Quantity' in
11168                   --http://files.oraclecorp.com/content/AllPublic/SharedFolders/CZ-Dev-Project-Documents-Public/12.1/Design/CZ_CP_Engine_UI_FD.doc
11169 
11170                   IF ( t_psn_instantiableflag ( v_index ) = h_instantiability ('mandatory')) THEN
11171 
11172                      l_var_min := 1;
11173                      l_var_max := 1;
11174 
11175                   ELSIF ( t_psn_instantiableflag ( v_index ) = h_instantiability ('optional')) THEN
11176 
11177                      l_var_min := 0;
11178                      l_var_max := 1;
11179 
11180                   ELSE
11181 
11182                      l_var_min := 0;
11183                      l_var_max := NVL ( t_psn_maximumselected( v_index ), cz_fce_compile_utils.const_max_integer);
11184 
11185                   END IF;
11186 
11187                   l_begin_date := NVL ( t_psn_effectivefrom ( v_index ), const_epoch_begin );
11188                   l_end_date := NVL ( t_psn_effectiveuntil ( v_index ), const_epoch_end );
11189 
11190                   IF ( l_begin_date < const_epoch_begin ) THEN l_begin_date := const_epoch_begin; END IF;
11191                   IF ( l_end_date > const_epoch_end ) THEN l_end_date := const_epoch_end; END IF;
11192 
11193                   --Note, that the value of the decimal quantity flag is taken using ps_node_id, not reference_id,
11194                   --because we are on the model node, not reference node.
11195 
11196                   emit_bommodelvar ( v_index
11197                                    , NVL ( h_psnid_decimalqtyflag ( TO_CHAR ( t_psn_psnodeid ( v_index ))), '0')
11198                                    , NVL ( t_psn_bomrequiredflag ( v_index ), '0')
11199                                    , NVL ( t_psn_minimumselected ( v_index ), 0 )
11200                                    , NVL ( t_psn_maximumselected ( v_index ), cz_fce_compile_utils.const_max_integer)
11201                                    , NVL ( t_psn_initialnumvalue ( v_index ), 0 )
11202                                    , l_var_min
11203                                    , l_var_max
11204                                    , l_begin_date
11205                                    , l_end_date
11206                                    , LPAD ( t_psn_effectiveusagemask ( v_index ), 16, '0')
11207                                    );
11208                END IF;
11209 
11210             WHEN h_psntypes('bomoptionclass') THEN --> bom option class
11211 
11212                emit_bomoptionclass_def( v_index, NVL ( t_psn_decimalqtyflag(v_index), '0'));
11213 
11214                l_begin_date := NVL ( t_psn_effectivefrom(v_index), const_epoch_begin);
11215                l_end_date := NVL ( t_psn_effectiveuntil(v_index), const_epoch_end);
11216 
11217                IF ( l_begin_date < const_epoch_begin) THEN l_begin_date := const_epoch_begin; END IF;
11218                IF ( l_end_date > const_epoch_end) THEN l_end_date := const_epoch_end; END IF;
11219 
11220                --Bug #7039221.
11221 
11222                l_var_max := 1;
11223 
11224                IF ( NVL ( t_psn_maximumselected ( v_index ), -1 ) = -1 ) THEN
11225 
11226                   l_var_max := h_psnid_numberofchildren ( TO_CHAR ( t_psn_psnodeid ( v_index )));
11227 
11228                END IF;
11229 
11230                emit_bomoptionclassvar ( v_index
11231                                       , NVL ( t_psn_decimalqtyflag ( v_index ), '0')
11232                                       , NVL ( t_psn_bomrequiredflag ( v_index ), '0')
11233                                       , NVL ( t_psn_minimum ( v_index ), 0 )
11234                                       , NVL ( t_psn_maximum ( v_index ), cz_fce_compile_utils.const_max_integer )
11235                                       , NVL ( t_psn_initialnumvalue ( v_index ), 0 )
11236                                       , NVL ( t_psn_minimumselected ( v_index ), 0 )
11237                                       , l_var_max
11238                                       , l_begin_date
11239                                       , l_end_date
11240                                       , LPAD ( t_psn_effectiveusagemask ( v_index ), 16, '0' )
11241                                       );
11242 
11243             WHEN h_psntypes('bomstandard') THEN --> bom standard item
11244 
11245                l_begin_date := NVL ( t_psn_effectivefrom(v_index), const_epoch_begin);
11246                l_end_date := NVL ( t_psn_effectiveuntil(v_index), const_epoch_end);
11247 
11248                IF ( l_begin_date < const_epoch_begin) THEN l_begin_date := const_epoch_begin; END IF;
11249                IF ( l_end_date > const_epoch_end) THEN l_end_date := const_epoch_end; END IF;
11250 
11251                emit_bomstandarditemvar ( v_index
11252                                        , NVL ( t_psn_decimalqtyflag(v_index), '0')
11253                                        , NVL ( t_psn_bomrequiredflag (v_index), '0')
11254                                        , NVL ( t_psn_minimum(v_index), 0)
11255                                        , NVL ( t_psn_maximum(v_index), cz_fce_compile_utils.const_max_integer)
11256                                        , NVL ( t_psn_initialnumvalue(v_index), 0)
11257                                        , l_begin_date
11258                                        , l_end_date
11259                                        , LPAD ( t_psn_effectiveusagemask( v_index ), 16, '0' )
11260                                        );
11261 
11262             WHEN h_psntypes('beginstructure') THEN --> begin structure data
11263 
11264                IF (NOT h_devlid_modelvisited.EXISTS ( TO_CHAR ( t_psn_devlprojectid (v_index)))) THEN
11265                    IF p_model_path IS NULL OR p_model_path = '' THEN
11266                     l_model_path := t_psn_name ( v_index - 1 );
11267                    ELSE
11268                     l_model_path := p_model_path || '/' || t_psn_name ( v_index - 1 );
11269                    END IF;
11270 
11271                    compile_logic_file ( t_psn_devlprojectid ( v_index ), const_logicfile_def, l_model_path );
11272 
11273                END IF;
11274 
11275             WHEN h_psntypes('beginport') THEN --> begin port variables
11276 
11277                compile_logic_file ( p_component_id, const_logicfile_port, p_model_path );
11278 
11279             WHEN h_psntypes('beginrule') THEN --> begin port variables
11280 
11281                compile_logic_file ( p_component_id, const_logicfile_constraint, p_model_path );
11282 
11283             WHEN h_psntypes('endstructure') THEN --> end structure data
11284 
11285               EXIT;
11286 
11287             ELSE
11288 
11289               NULL;
11290 
11291         END CASE;
11292      END LOOP;
11293      ----------------------------------------------------------------------------------
11294      WHEN const_logicfile_port THEN
11295      ----------------------------------------------------------------------------------
11296      LOOP
11297         v_index := v_index + 1;
11298 
11299         CASE t_psn_psnodetype(v_index)
11300 
11301             WHEN h_psntypes('component') THEN --> component
11302 
11303                IF (t_psn_virtualflag ( v_index ) = h_instantiability ('nonvirtual')) THEN --> component instance
11304 
11305                   emit_instancesetvar ( v_index, t_psn_minimum(v_index), t_psn_maximum(v_index));
11306 
11307                ELSE --> mandatory component
11308 
11309                   emit_singletonvar (v_index);
11310 
11311                END IF; --> component
11312 
11313             WHEN h_psntypes('reference') THEN --> reference
11314 
11315                IF ( h_psnid_psnodetype ( TO_CHAR ( t_psn_referenceid (v_index))) = h_psntypes('bommodel')) THEN --> reference to BOM
11316 
11317                       --See Section 23.13.2 'BOM Instantiatibility and Quantity' in
11318                       --http://files.oraclecorp.com/content/AllPublic/SharedFolders/CZ-Dev-Project-Documents-Public/12.1/Design/CZ_CP_Engine_UI_FD.doc
11319 
11320                       IF ( t_psn_instantiableflag ( v_index ) = h_instantiability ('mandatory')) THEN
11321 
11322                          l_var_min := 1;
11323                          l_var_max := 1;
11324 
11325                       ELSIF ( t_psn_instantiableflag ( v_index ) = h_instantiability ('optional')) THEN
11326 
11327                          l_var_min := 0;
11328                          l_var_max := 1;
11329 
11330                       ELSE
11331 
11332                          l_var_min := 0;
11333                          l_var_max := NVL ( t_psn_maximumselected(v_index), cz_fce_compile_utils.const_max_integer);
11334 
11335                       END IF;
11336 
11337                       l_begin_date := NVL ( t_psn_effectivefrom(v_index), const_epoch_begin );
11338                       l_end_date := NVL ( t_psn_effectiveuntil(v_index), const_epoch_end );
11339 
11340                       IF ( l_begin_date < const_epoch_begin) THEN l_begin_date := const_epoch_begin; END IF;
11341                       IF ( l_end_date > const_epoch_end) THEN l_end_date := const_epoch_end; END IF;
11342 
11343                       emit_bommodelvar ( v_index
11344                                        , NVL ( h_psnid_decimalqtyflag ( TO_CHAR ( t_psn_referenceid (v_index))), '0')
11345                                        , NVL ( t_psn_bomrequiredflag (v_index), '0')
11346                                        , NVL ( t_psn_minimumselected(v_index), 0)
11347                                        , NVL ( t_psn_maximumselected(v_index), cz_fce_compile_utils.const_max_integer)
11348                                        , NVL ( t_psn_initialnumvalue(v_index), 0)
11349                                        , l_var_min
11350                                        , l_var_max
11351                                        , l_begin_date
11352                                        , l_end_date
11353                                        , LPAD ( t_psn_effectiveusagemask ( v_index ), 16, '0' )
11354                                        );
11355 
11356                ELSE --> component reference
11357 
11358                       emit_instancesetvar ( v_index, t_psn_minimum(v_index), t_psn_maximum(v_index));
11359 
11360                END IF;
11361 
11362             WHEN h_psntypes('connector') THEN --> connector
11363 
11364                emit_connectorsetvar ( v_index, t_psn_minimum(v_index), t_psn_maximum(v_index));
11365 
11366             WHEN h_psntypes('endport') THEN --> end port variables
11367 
11368               EXIT;
11369 
11370             ELSE
11371 
11372               NULL;
11373 
11374         END CASE;
11375      END LOOP;
11376      ----------------------------------------------------------------------------------
11377      WHEN const_logicfile_constraint THEN
11378      ----------------------------------------------------------------------------------
11379 
11380      --First generate all reverse port relations defined in the structure, then compile
11381      --constraints.
11382 
11383      l_reverseportcount := 0;
11384 
11385      LOOP
11386         v_index := v_index + 1;
11387 
11388         CASE t_psn_psnodetype(v_index)
11389 
11390             WHEN h_psntypes('endrule') THEN --> end port variables
11391 
11392               EXIT;
11393 
11394             ELSE
11395 
11396               emit_reverseport ( v_index );
11397               l_reverseportcount := l_reverseportcount + 1;
11398 
11399         END CASE;
11400      END LOOP;
11401 
11402      --#<optimization-reverseport>: Pop the nulls here in bulk.
11403 
11404      emit_pop ( l_reverseportcount );
11405 
11406      compile_constraints ();
11407      ----------------------------------------------------------------------------------
11408      END CASE;
11409 
11410      emit_return ();
11411      spool_logic_file ();
11412 
11413 END compile_logic_file;
11414 ---------------------------------------------------------------------------------------
11415 BEGIN --> compile_logic_
11416 
11417     IF ( x_run_id IS NULL OR x_run_id = 0 ) THEN
11418 
11419       SELECT cz_xfr_run_infos_s.NEXTVAL INTO x_run_id FROM DUAL;
11420 
11421     END IF;
11422 
11423     --Read effectivity sets into memory and build hash tables for quick lookup.
11424 
11425     SELECT effectivity_set_id, effective_from, effective_until
11426       BULK COLLECT INTO t_effset_effectivitysetid, t_effset_effectivefrom, t_effset_effectiveuntil
11427       FROM cz_effectivity_sets
11428      WHERE deleted_flag = '0';
11429 
11430     FOR i IN 1..t_effset_effectivitysetid.COUNT LOOP
11431 
11432        h_effsetid_effectivefrom ( TO_CHAR ( t_effset_effectivitysetid ( i ))) := t_effset_effectivefrom ( i );
11433        h_effsetid_effectiveuntil ( TO_CHAR ( t_effset_effectivitysetid ( i ))) := t_effset_effectiveuntil ( i );
11434 
11435     END LOOP;
11436 
11437    --Pass 1. Process the model data to transform it into the internal format.
11438 
11439    v_index := 1;
11440    h_devlid_modelvisited.DELETE;
11441    read_model_data ( p_object_id );
11442 
11443    --Pass 2. Compilation.
11444 
11445    v_index := 1;
11446    h_devlid_modelvisited.DELETE;
11447    compile_logic_file ( p_object_id, const_logicfile_def );
11448 
11449    IF ( p_two_phase_commit = 0 ) THEN COMMIT; END IF;
11450 
11451 EXCEPTION
11452    WHEN CZ_LOGICGEN_ERROR THEN
11453           ROLLBACK;
11454    WHEN CZ_LOGICGEN_SYS_ERROR THEN
11455           ROLLBACK;
11456    WHEN OTHERS THEN
11457           ROLLBACK;
11458           -- Unknown Error:
11459           report_and_raise_sys_error(
11460             p_message => CZ_UTILS.GET_TEXT(CZ_FCE_UE_GENERIC_PREFIX) || DBMS_UTILITY.FORMAT_ERROR_STACK,
11461             p_run_id => x_run_id,
11462             p_model_id => p_object_id,
11463             p_error_stack => DBMS_UTILITY.FORMAT_ERROR_STACK || ' Error backtrace: ' || DBMS_UTILITY.FORMAT_ERROR_BACKTRACE,
11464             p_raise_exception => FALSE
11465           );
11466 
11467 END compile_logic_;
11468 ---------------------------------------------------------------------------------------
11469 --Default method to generate logic in debug mode.
11470 
11471 PROCEDURE debug_logic ( p_object_id IN NUMBER
11472                       , x_run_id    IN OUT NOCOPY NUMBER
11473                       ) IS
11474 BEGIN
11475 
11476    compile_logic_ ( p_object_id, x_run_id, 0, 1 );
11477 
11478 END debug_logic;
11479 ---------------------------------------------------------------------------------------
11480 --Default method to generate logic for a model in the database.
11481 
11482 PROCEDURE compile_logic ( p_object_id IN NUMBER
11483                         , x_run_id    IN OUT NOCOPY NUMBER
11484                         ) IS
11485 BEGIN
11486 
11487    compile_logic_ ( p_object_id, x_run_id, 0, 0 );
11488 
11489 END compile_logic;
11490 ---------------------------------------------------------------------------------------
11491 --This method is not required in FCE as there is no DDL in generation of property-based
11492 --compatibility rules (Re: bug #2028790). The caller of this method is responsible for
11493 --commiting the generated logic to the database.
11494 
11495 PROCEDURE compile_logic__ ( p_object_id IN NUMBER
11496                           , p_run_id    IN NUMBER
11497                           ) IS
11498   l_run_id  NUMBER := p_run_id;
11499 
11500 BEGIN
11501 
11502    compile_logic_ ( p_object_id, l_run_id, 1, 0 );
11503 
11504 END compile_logic__;
11505 ---------------------------------------------------------------------------------------
11506 BEGIN
11507 
11508   CZ_FCE_DATA.populate_fce_data ();
11509 
11510 END;