1 PACKAGE BODY CZ_LOGIC_GEN AS
2 /* $Header: czlcegnb.pls 120.37.12020000.5 2013/01/11 21:39:21 smanna ship $ */
3 ---------------------------------------------------------------------------------------
4 TYPE tShortStringArray IS TABLE OF VARCHAR2(10) INDEX BY BINARY_INTEGER;
5 TYPE tIntegerArray IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; --kdande; Bug 6881902; 11-Mar-2008
6 TYPE tIntegerArray_idx_vc2 IS TABLE OF NUMBER INDEX BY VARCHAR2(15);
7 TYPE refCursor IS REF CURSOR;
8 OperatorLiterals tShortStringArray;
9 OperatorLetters tShortStringArray;
10 CodeByCodeLookup tIntegerArray;
11 GenHeader VARCHAR2(100) := '$Header: czlcegnb.pls 120.37.12020000.5 2013/01/11 21:39:21 smanna ship $';
12
13 DATATYPE_TRANSLATABLE_PROP CONSTANT PLS_INTEGER := 8;
14 CZ_SEQUENCE_INCREMENT CONSTANT NUMBER := 20;
15 ---------------------------------------------------------------------------------------
16 PROCEDURE GENERATE_LOGIC_(inDevlProjectId IN NUMBER,
17 thisRunId IN OUT NOCOPY NUMBER,
18 TwoPhaseCommit IN PLS_INTEGER)
19 IS
20
21 TYPE tStringArray IS TABLE OF VARCHAR2(4000) INDEX BY BINARY_INTEGER;
22 TYPE tNumberArray IS TABLE OF NUMBER INDEX BY BINARY_INTEGER; --kdande; Bug 6881902; 11-Mar-2008
23 TYPE tNumberArray_idx_vc2 IS TABLE OF NUMBER INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
24 TYPE tDateArray IS TABLE OF DATE INDEX BY BINARY_INTEGER;
25 TYPE table_of_number_tables IS TABLE OF tNumberArray INDEX BY BINARY_INTEGER;
26 TYPE table_of_tNumberArray_idx_vc2 IS TABLE OF tNumberArray_idx_vc2 INDEX BY BINARY_INTEGER; -- jonatara:bug7041718
27 TYPE tVarcharHashType IS TABLE OF VARCHAR2(4000) INDEX BY VARCHAR2(4000);
28
29 TYPE tPsNodeId IS TABLE OF cz_ps_nodes.ps_node_id%TYPE INDEX BY VARCHAR2(15);
30 TYPE tItemId IS TABLE OF cz_ps_nodes.item_id%TYPE INDEX BY BINARY_INTEGER;
31 TYPE tPersistentId IS TABLE OF cz_ps_nodes.persistent_node_id%TYPE INDEX BY BINARY_INTEGER;
32 TYPE tPersistentId_idx_vc2 IS TABLE OF cz_ps_nodes.persistent_node_id%TYPE INDEX BY VARCHAR2(15);
33 TYPE tPsNodeType IS TABLE OF cz_ps_nodes.ps_node_type%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
34 TYPE tInitialValue IS TABLE OF cz_ps_nodes.initial_value%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
35 TYPE tParentId IS TABLE OF cz_ps_nodes.parent_id%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
36 TYPE tMinimum IS TABLE OF cz_ps_nodes.minimum%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
37 TYPE tMaximum IS TABLE OF cz_ps_nodes.maximum%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
38 TYPE tVirtualFlag IS TABLE OF cz_ps_nodes.virtual_flag%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
39 TYPE tFeatureType IS TABLE OF cz_ps_nodes.feature_type%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
40 TYPE tName IS TABLE OF cz_ps_nodes.name%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
41 TYPE tDescriptionId IS TABLE OF cz_ps_nodes.intl_text_id%TYPE INDEX BY BINARY_INTEGER;
42 TYPE tMinimumSel IS TABLE OF cz_ps_nodes.minimum_selected%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
43 TYPE tMaximumSel IS TABLE OF cz_ps_nodes.maximum_selected%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
44 TYPE tBomRequired IS TABLE OF cz_ps_nodes.bom_required_flag%TYPE INDEX BY BINARY_INTEGER;
45 TYPE tReferenceId IS TABLE OF cz_ps_nodes.reference_id%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
46 TYPE tUsageMask IS TABLE OF cz_ps_nodes.effective_usage_mask%TYPE INDEX BY BINARY_INTEGER;
47 TYPE tDecimalQty IS TABLE OF cz_ps_nodes.decimal_qty_flag%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
48 TYPE tIbTrackable IS TABLE OF cz_ps_nodes.ib_trackable%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
49 TYPE tAccumulator IS TABLE OF cz_ps_nodes.accumulator_flag%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
50 TYPE tInitialNumValue IS TABLE OF cz_ps_nodes.initial_num_value%TYPE INDEX BY BINARY_INTEGER;
51 TYPE tInstantiableFlag IS TABLE OF cz_ps_nodes.instantiable_flag%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
52 TYPE tShippableFlag IS TABLE OF cz_ps_nodes.shippable_item_flag%TYPE INDEX BY BINARY_INTEGER;
53 TYPE tTransactableFlag IS TABLE OF cz_ps_nodes.inventory_transactable_flag%TYPE INDEX BY BINARY_INTEGER;
54 TYPE tAtoFlag IS TABLE OF cz_ps_nodes.assemble_to_order_flag%TYPE INDEX BY BINARY_INTEGER;
55 TYPE tSerializableFlag IS TABLE OF cz_ps_nodes.serializable_item_flag%TYPE INDEX BY BINARY_INTEGER;
56
57 TYPE tSetEffFrom IS TABLE OF cz_effectivity_sets.effective_from%TYPE INDEX BY BINARY_INTEGER;
58 TYPE tSetEffUntil IS TABLE OF cz_effectivity_sets.effective_until%TYPE INDEX BY BINARY_INTEGER;
59 TYPE tSetEffId IS TABLE OF cz_effectivity_sets.effectivity_set_id%TYPE INDEX BY BINARY_INTEGER;
60 TYPE tSetName IS TABLE OF cz_effectivity_sets.name%TYPE INDEX BY BINARY_INTEGER;
61
62 TYPE tHeaderId IS TABLE OF cz_lce_headers.lce_header_id%TYPE INDEX BY VARCHAR2(15);
63 TYPE tExplNodeId IS TABLE OF cz_model_ref_expls.component_id%TYPE INDEX BY BINARY_INTEGER; --kdande; Bug 6881902; 11-Mar-2008
64 TYPE tExplNodeId_idx_vc2 IS TABLE OF cz_model_ref_expls.component_id%TYPE INDEX BY VARCHAR2(15); --kdande; Bug 6881902; 11-Mar-2008
65
66 TYPE tExprType IS TABLE OF cz_expression_nodes.expr_type%TYPE INDEX BY BINARY_INTEGER;
67 TYPE tExprSubtype IS TABLE OF cz_expression_nodes.expr_subtype%TYPE INDEX BY BINARY_INTEGER;
68 TYPE tExprId IS TABLE OF cz_expression_nodes.expr_node_id%TYPE INDEX BY BINARY_INTEGER;
69 TYPE tExprParentId IS TABLE OF cz_expression_nodes.expr_parent_id%TYPE INDEX BY BINARY_INTEGER;
70 TYPE tExprTemplateId IS TABLE OF cz_expression_nodes.template_id%TYPE INDEX BY BINARY_INTEGER;
71 TYPE tExprParamIndex IS TABLE OF cz_expression_nodes.param_index%TYPE INDEX BY BINARY_INTEGER;
72 TYPE tExprArgumentIndex IS TABLE OF cz_expression_nodes.argument_index%TYPE INDEX BY BINARY_INTEGER;
73 TYPE tExprArgumentName IS TABLE OF cz_expression_nodes.argument_name%TYPE INDEX BY BINARY_INTEGER;
74 TYPE tExprDataType IS TABLE OF cz_expression_nodes.data_type%TYPE INDEX BY BINARY_INTEGER;
75 TYPE tExpressId IS TABLE OF cz_expression_nodes.express_id%TYPE INDEX BY BINARY_INTEGER;
76 TYPE tExprDataValue IS TABLE OF cz_expression_nodes.data_value%TYPE INDEX BY BINARY_INTEGER;
77 TYPE tExprPropertyId IS TABLE OF cz_expression_nodes.property_id%TYPE INDEX BY BINARY_INTEGER;
78 TYPE tPresentType IS TABLE OF cz_expressions.present_type%TYPE INDEX BY BINARY_INTEGER;
79 TYPE tOptionId IS TABLE OF cz_des_chart_cells.secondary_opt_id%TYPE INDEX BY BINARY_INTEGER;
80 TYPE tConsequentFlag IS TABLE OF cz_expression_nodes.consequent_flag%TYPE INDEX BY BINARY_INTEGER;
81 TYPE tDesFeatureType IS TABLE OF cz_des_chart_features.feature_type%TYPE INDEX BY BINARY_INTEGER;
82 TYPE tExprDataNumValue IS TABLE OF cz_expression_nodes.data_num_value%TYPE INDEX BY BINARY_INTEGER;
83 TYPE tExprArgSignature IS TABLE OF cz_expression_nodes.argument_signature_id%TYPE INDEX BY BINARY_INTEGER;
84 TYPE tExprParSignature IS TABLE OF cz_expression_nodes.param_signature_id%TYPE INDEX BY BINARY_INTEGER;
85
86 TYPE tRuleId IS TABLE OF cz_rules.rule_id%TYPE INDEX BY BINARY_INTEGER;
87 TYPE tRuleName IS TABLE OF cz_rules.name%TYPE INDEX BY BINARY_INTEGER;
88
89 TYPE tArgumentName IS TABLE OF cz_signature_arguments.argument_name%TYPE INDEX BY BINARY_INTEGER;
90 TYPE tArgumentIndex IS TABLE OF cz_signature_arguments.argument_index%TYPE INDEX BY BINARY_INTEGER;
91 TYPE tDataType IS TABLE OF cz_signature_arguments.data_type%TYPE INDEX BY BINARY_INTEGER;
92
93 commit_counter PLS_INTEGER := 0;
94 CommitBlockSize PLS_INTEGER;
95 OptimizeNotTrue PLS_INTEGER;
96 OptimizeAllAnyOf PLS_INTEGER;
97 GenerateGatedCombo PLS_INTEGER;
98 ChangeChildrenOrder PLS_INTEGER;
99 StopOnFatalRuleError PLS_INTEGER;
100 GenerateUpdatedOnly PLS_INTEGER;
101 StoreNlsCharacters VARCHAR2(16) := NlsNumericCharacters;
102
103 rootProjectName cz_devl_projects.name%TYPE;
104 rootProjectType cz_devl_projects.model_type%TYPE;
105
106 NewHeaders tIntegerArray;
107 OldHeaders tIntegerArray;
108 NewHeadersComponents tIntegerArray;
109 NewHeadersExplosions tIntegerArray;
110 counterNewHeaders PLS_INTEGER := 1;
111
112 IsLogicGenerated tIntegerArray_idx_vc2;
113 modelChecked tIntegerArray_idx_vc2;
114 vSeqNbrByHeader tNumberArray_idx_vc2; --kdande; Bug 6881902; 11-Mar-2008
115 v_HeaderByAccId tHeaderId;
116 v_HeaderByNotTrueId tHeaderId;
117 h_HeaderPiDefined tStringArray;
118 h_HeaderEDefined tStringArray;
119
120 memoryTemplateStart tIntegerArray;
121 memoryTemplateEnd tIntegerArray;
122 v_tTmplNodeId tExplNodeId;
123 v_tTmplType tExprType;
124 v_tTmplSubtype tExprSubtype;
125 v_tTmplId tExprId;
126 v_tTmplParentId tExprParentId;
127 v_tTmplTemplateId tExprTemplateId;
128 v_tTmplExpressId tExpressId;
129 v_tTmplPsNodeId tExplNodeId;
130 v_tTmplDataValue tExprDataValue;
131 v_tTmplDataType tExprDataType;
132 v_tTmplPropertyId tExprPropertyId;
133 v_tTmplArgumentIndex tExprArgumentIndex;
134 v_tTmplArgumentName tExprArgumentName;
135 v_tTmplConsequent tConsequentFlag;
136
137 t_RuleId tRuleId;
138 t_SignatureId tRuleId;
139 t_RuleName tRuleName;
140 h_SeededName tRuleName;
141 h_ReportName tRuleName;
142 h_SignatureId tRuleId;
143 h_SignatureDataType tIntegerArray;
144
145 glPsNodeId tPsNodeId;
146 glItemId tItemId;
147 glPersistentId tPersistentId_idx_vc2;
148 glReferenceId tReferenceId;
149 glPsNodeType tPsNodeType;
150 glIndexByPsNodeId tIntegerArray_idx_vc2;
151 glLastChildIndex tIntegerArray_idx_vc2;
152 glParentId tParentId;
153 glFeatureType tFeatureType;
154 glName tName;
155 glBomRequired tBomRequired;
156 glHeaderByPsNodeId tNumberArray_idx_vc2; --kdande; Bug 6881902; 11-Mar-2008
157 glEffFrom tDateArray;
158 glEffUntil tDateArray;
159 glUsageMask tUsageMask;
160 glMinimum tMinimum;
161 glMaximum tMaximum;
162 glMinimumSel tMinimumSel;
163 glMaximumSel tMaximumSel;
164 glVirtualFlag tVirtualFlag;
165 glDecimalQty tDecimalQty;
166 glIbTrackable tIbTrackable;
167 glInitialValue tInitialValue;
168 glAccumulator tAccumulator;
169 glInitialNumValue tInitialNumValue;
170 glInstantiableFlag tInstantiableFlag;
171 featOptionsCount tIntegerArray_idx_vc2;
172
173 v_NodeIdByComponent tExplNodeId_idx_vc2; --kdande; Bug 6881902; 11-Mar-2008
174
175 --Support for effectivity sets
176 gvEffFrom tSetEffFrom;
177 gvEffUntil tSetEffUntil;
178 gvSetId tSetEffId;
179 gvIndexBySetId tIntegerArray;
180
181 globalCount PLS_INTEGER := 1;
182 --Just to support debugging
183 nDebug PLS_INTEGER := 7777777;
184 --Auxiliery parameters for reporting
185 nParam NUMBER; --kdande; Bug 6881902; 11-Mar-2008
186 errorMessage VARCHAR2(4000);
187 thisName VARCHAR2(4000);
188 parentName VARCHAR2(4000);
189
190 --Referencing level indicator and model stack
191 globalLevel PLS_INTEGER := 0;
192 globalStack tIntegerArray;
193 globalRef tIntegerArray;
194 globalInstance tIntegerArray;
195 instanceModel tIntegerArray_idx_vc2;
196 trackableAncestor tIntegerArray_idx_vc2;
197
198 --Set of data for implementing the locking mechanism
199 l_msg_data VARCHAR2(4000);
200 l_msg_count NUMBER := 0;
201 l_return_status VARCHAR2(1);
202 l_lock_status VARCHAR2(1) := FND_API.G_RET_STS_SUCCESS;
203 l_locked_models cz_security_pvt.number_type_tbl;
204 FAILED_TO_LOCK_MODEL EXCEPTION;
205
206 --bug fix 8689041 Modified the criteria to retrieve last_logic_update and logic creation_date
207 logicSQL VARCHAR2(4000) := 'SELECT proj.devl_project_id, max(proj.last_logic_update),max(head.creation_date)' ||
208 ' FROM cz_devl_projects proj, cz_model_ref_expls expl, cz_lce_headers head' ||
209 ' WHERE proj.deleted_flag = ''' || FLAG_NOT_DELETED ||
210 ''' AND expl.deleted_flag = ''' || FLAG_NOT_DELETED ||
211 ''' AND head.deleted_flag = ''' || FLAG_NOT_DELETED ||
212 ''' AND expl.node_depth = 1' ||
213 ' AND expl.model_id = :1' ||
214 ' AND head.net_type in (1,2)' ||
215 ' AND proj.devl_project_id = expl.component_id' ||
216 ' AND proj.devl_project_id = head.component_id' ||
217 ' AND head.component_id = head.devl_project_id' ||
218 ' GROUP BY proj.devl_project_id';
219
220
221 h_containerReferred tIntegerArray_idx_vc2;
222 containerReferred VARCHAR2(4000) :=
223
224 'SELECT 1 FROM DUAL WHERE EXISTS' ||
225 ' (SELECT model_id FROM cz_model_ref_expls' ||
226 ' WHERE deleted_flag = ''' || FLAG_NOT_DELETED || '''' ||
227 ' AND ps_node_type IN (' || PS_NODE_TYPE_REFERENCE || ', ' || PS_NODE_TYPE_CONNECTOR || ')' ||
228 ' AND component_id = :1' ||
229 ' AND (SELECT model_type FROM cz_devl_projects' ||
230 ' WHERE devl_project_id = model_id) = ''' || MODEL_TYPE_CONTAINER_MODEL || ''')';
231
232 GENERATION_REQUIRED CONSTANT PLS_INTEGER := 1;
233 GENERATION_NOT_REQUIRED CONSTANT PLS_INTEGER := 2;
234
235 table_name_generator PLS_INTEGER := 1;
236 table_hash_propval tVarcharHashType;
237 ---------------------------------------------------------------------------------------
238 --Bug #5727549.
239
240 last_id_allocated NUMBER := NULL;
241 next_id_to_use NUMBER := 0;
242
243 FUNCTION next_lce_header_id RETURN NUMBER IS
244 id_to_return NUMBER;
245 BEGIN
246 IF((last_id_allocated IS NULL) OR
247 (next_id_to_use = (NVL(last_id_allocated, 0) + CZ_SEQUENCE_INCREMENT)))THEN
248
249 SELECT cz_lce_headers_s.NEXTVAL INTO last_id_allocated FROM DUAL;
250 next_id_to_use := last_id_allocated;
251 END IF;
252
253 id_to_return := next_id_to_use;
254 next_id_to_use := next_id_to_use + 1;
255 RETURN id_to_return;
256 END next_lce_header_id;
257 ---------------------------------------------------------------------------------------
258 --Reporting procedure
259
260 PROCEDURE REPORT(inMessage IN VARCHAR2, inUrgency IN PLS_INTEGER) IS
261 BEGIN
262
263 INSERT INTO cz_db_logs (message, statuscode, caller, urgency, run_id)
264 VALUES (inMessage, nDebug, 'Logic Generator', inUrgency, thisRunId);
265
266 EXCEPTION
267 WHEN OTHERS THEN
268 RAISE CZ_G_UNABLE_TO_REPORT_ERROR;
269 END;
270 ---------------------------------------------------------------------------------------
271 PROCEDURE SET_NLS_CHARACTERS(p_nls_characters IN VARCHAR2) IS
272 BEGIN
273 IF(NlsNumericCharacters <> StoreNlsCharacters)THEN
274
275 EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_NUMERIC_CHARACTERS = ''' || p_nls_characters || '''';
276 END IF;
277 END;
278 ---------------------------------------------------------------------------------------
279 PROCEDURE GENERATE_COMPONENT_TREE(inComponentId IN NUMBER,
280 inProjectId IN NUMBER,
281 inParentLogicHeaderId IN NUMBER)
282 IS
283
284 TYPE tNodeDepth IS TABLE OF cz_model_ref_expls.node_depth%TYPE INDEX BY BINARY_INTEGER;
285 TYPE tNodeType IS TABLE OF cz_model_ref_expls.ps_node_type%TYPE INDEX BY BINARY_INTEGER;
286 TYPE tVirtualFlag IS TABLE OF cz_model_ref_expls.virtual_flag%TYPE INDEX BY BINARY_INTEGER;
287 TYPE tParentId IS TABLE OF cz_model_ref_expls.component_id%TYPE INDEX BY BINARY_INTEGER;
288 TYPE tPsNodeId IS TABLE OF cz_model_ref_expls.component_id%TYPE INDEX BY BINARY_INTEGER;
289 TYPE tChildModelExpl IS TABLE OF cz_model_ref_expls.child_model_expl_id%TYPE INDEX BY BINARY_INTEGER;
290 TYPE tExplNodeType IS TABLE OF cz_model_ref_expls.expl_node_type%TYPE INDEX BY BINARY_INTEGER;
291 --kdande; Bug 6881902; 11-Mar-2008; Made the following PLSQL types local to the procedure as they are used for Bulk Collects
292 TYPE tPsNodeType IS TABLE OF cz_ps_nodes.ps_node_type%TYPE INDEX BY BINARY_INTEGER;
293 TYPE tReferenceId IS TABLE OF cz_ps_nodes.reference_id%TYPE INDEX BY BINARY_INTEGER;
294 TYPE tDecimalQty IS TABLE OF cz_ps_nodes.decimal_qty_flag%TYPE INDEX BY BINARY_INTEGER;
295 TYPE tIbTrackable IS TABLE OF cz_ps_nodes.ib_trackable%TYPE INDEX BY BINARY_INTEGER;
296 TYPE tAccumulator IS TABLE OF cz_ps_nodes.accumulator_flag%TYPE INDEX BY BINARY_INTEGER;
297 TYPE tInstantiableFlag IS TABLE OF cz_ps_nodes.instantiable_flag%TYPE INDEX BY BINARY_INTEGER;
298 TYPE tFeatureType IS TABLE OF cz_ps_nodes.feature_type%TYPE INDEX BY BINARY_INTEGER;
299 TYPE tName IS TABLE OF cz_ps_nodes.name%TYPE INDEX BY BINARY_INTEGER;
300 TYPE tInitialValue IS TABLE OF cz_ps_nodes.initial_value%TYPE INDEX BY BINARY_INTEGER;
301 TYPE tMinimum IS TABLE OF cz_ps_nodes.minimum%TYPE INDEX BY BINARY_INTEGER;
302 TYPE tMaximum IS TABLE OF cz_ps_nodes.maximum%TYPE INDEX BY BINARY_INTEGER;
303 TYPE tMinimumSel IS TABLE OF cz_ps_nodes.minimum_selected%TYPE INDEX BY BINARY_INTEGER;
304 TYPE tMaximumSel IS TABLE OF cz_ps_nodes.maximum_selected%TYPE INDEX BY BINARY_INTEGER;
305
306 ntPsNodeId tPsNodeId;
307 ntItemId tItemId;
308 ntPersistentId tPersistentId;
309 ntPsNodeType tPsNodeType;
310 ntInitialValue tInitialValue;
311 ntParentId tParentId;
312 ntMinimum tMinimum;
313 ntMaximum tMaximum;
314 ntVirtualFlag tVirtualFlag;
315 ntFeatureType tFeatureType;
316 ntName tName;
317 ntDescriptionId tDescriptionId;
318 ntMinimumSel tMinimumSel;
319 ntMaximumSel tMaximumSel;
320 ntBomRequired tBomRequired;
321 ntReferenceId tReferenceId;
322 dtEffFrom tDateArray;
323 dtEffUntil tDateArray;
324 vtUsageMask tUsageMask;
325 ntEffSetId tSetEffId;
326 ntDecimalQty tDecimalQty;
327 ntIbTrackable tIbTrackable;
328 ntAccumulator tAccumulator;
329 ntInitialNumValue tInitialNumValue;
330 ntInstantiableFlag tInstantiableFlag;
331 ntShippableFlag tShippableFlag;
332 ntTransactableFlag tTransactableFlag;
333 ntAtoFlag tAtoFlag;
334 ntSerializableFlag tSerializableFlag;
335
336 v_tNodeDepth tNodeDepth;
337 v_tNodeType tNodeType;
338 v_tVirtualFlag tVirtualFlag;
339 v_tParentId tParentId;
340 v_tPsNodeId tPsNodeId;
341 v_tReferringId tPsNodeId;
342 v_tChildModelExpl tChildModelExpl;
343 v_tExplNodeType tExplNodeType;
344 v_NodeId tExplNodeId;
345
346 v_IndexByNodeId tIntegerArray_idx_vc2;
347 v_TypeByExplId tExplNodeType;
348
349 thisComponentExplId cz_model_ref_expls.model_ref_expl_id%TYPE;
350 thisProjectId cz_devl_projects.devl_project_id%TYPE;
351 thisProjectName cz_devl_projects.name%TYPE;
352 thisProjectType cz_devl_projects.model_type%TYPE;
353 thisRootExplIndex PLS_INTEGER;
354
355 nStructureHeaderId cz_lce_headers.lce_header_id%TYPE;
356 PrevEffFrom DATE := EpochBeginDate;
357 PrevEffUntil DATE := EpochEndDate;
358 PrevUsageMask cz_ps_nodes.effective_usage_mask%TYPE := AnyUsageMask;
359 CurrentEffFrom DATE;
360 CurrentEffUntil DATE;
361 CurrentUsageMask cz_ps_nodes.effective_usage_mask%TYPE;
362 FeatureEffFrom DATE;
363 FeatureEffUntil DATE;
364 FeatureUsageMask cz_ps_nodes.effective_usage_mask%TYPE;
365 nSequenceNbr NUMBER := 1;
366 vLogicText VARCHAR2(4000);
367 vLogicLine VARCHAR2(4000);
368 vLogicName VARCHAR2(4000);
369
370 CurrentFromDate VARCHAR2(25);
371 CurrentUntilDate VARCHAR2(25);
372 localMinString VARCHAR2(25);
373 localMaxString VARCHAR2(25);
374
375 CurrentlyPacking PLS_INTEGER;
376 LastPacked PLS_INTEGER := PACKING_GENERIC;
377 generatingFeature PLS_INTEGER := 0;
378
379 i PLS_INTEGER;
380 j PLS_INTEGER;
381 localCount PLS_INTEGER;
382 optionCounter PLS_INTEGER;
383 trackableContext NUMBER; -- jonatara:bug7041718
384 instantiableContext NUMBER; -- jonatara:bug7041718
385
386 -- LA 13733007 : OC with No children
387 TYPE tNoChildOCName IS TABLE OF cz_ps_nodes.name%TYPE INDEX BY BINARY_INTEGER;
388 TYPE tNoChildOCModelName IS TABLE OF cz_rp_entries.name%TYPE INDEX BY BINARY_INTEGER;
389 lNoChildOCName tNoChildOCName ;
390 lNoChildOCModelName tNoChildOCModelName;
391
392 ---------------------------------------------------------------------------------------
393 PROCEDURE PACK IS
394 BEGIN
395 IF(vLogicLine IS NOT NULL)THEN
396 IF(LENGTHB(vLogicText) + LENGTHB(vLogicLine)>2000)THEN
397
398 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
399 (nStructureHeaderId, nSequenceNbr, vLogicText);
400 vLogicText := NULL;
401 nSequenceNbr := nSequenceNbr + 1;
402
403 --Commit in blocks if not disabled
404
405 IF(TwoPhaseCommit = 0)THEN
406 commit_counter := commit_counter + 1;
407 IF(commit_counter = CommitBlockSize)THEN
408 COMMIT;
409 commit_counter := 0;
410 END IF;
411 END IF;
412 END IF;
413 vLogicText := vLogicText || vLogicLine;
414 vLogicLine := NULL;
415
416 LastPacked := PACKING_GENERIC;
417
418 END IF;
419 END PACK;
420 ---------------------------------------------------------------------------------------
421 PROCEDURE PACK_EFFECTIVITY IS
422 BEGIN
423 IF(vLogicLine IS NOT NULL)THEN
424 IF(LENGTHB(vLogicText) + LENGTHB(vLogicLine)>2000)THEN
425
426 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
427 (nStructureHeaderId, nSequenceNbr, vLogicText);
428 vLogicText := NULL;
429 nSequenceNbr := nSequenceNbr + 1;
430
431 --Commit in blocks if not disabled
432
433 IF(TwoPhaseCommit = 0)THEN
434 commit_counter := commit_counter + 1;
435 IF(commit_counter = CommitBlockSize)THEN
436 COMMIT;
437 commit_counter := 0;
438 END IF;
439 END IF;
440 END IF;
441
442 IF(LastPacked = PACKING_EFFECTIVITY AND CurrentlyPacking = LastPacked)THEN
443
444 --We are inserting one effectivity statement after another. Replace the last
445 --one with the current one.
446
447 vLogicText := SUBSTR(vLogicText, 1, INSTR(vLogicText, 'EFF', -1, 1) - 1) || vLogicLine;
448
449 ELSE
450 vLogicText := vLogicText || vLogicLine;
451 END IF;
452
453 vLogicLine := NULL;
454 LastPacked := CurrentlyPacking;
455
456 END IF;
457 END PACK_EFFECTIVITY;
458 ---------------------------------------------------------------------------------------
459 PROCEDURE GENERATE_EFFECTIVITY_LOGIC(inCurrentEffFrom IN DATE,
460 inCurrentEffUntil IN DATE,
461 inCurrentUsageMask IN VARCHAR2) IS
462 BEGIN
463 IF((inCurrentEffFrom <> PrevEffFrom) OR (inCurrentEffUntil <> PrevEffUntil) OR
464 (inCurrentUsageMask <> PrevUsageMask))THEN
465
466 vLogicLine := LTRIM(inCurrentUsageMask, '0');
467 IF(vLogicLine IS NOT NULL) THEN
468 vLogicLine := EffUsagePrefix || vLogicLine;
469 END IF;
470
471 IF(inCurrentEffFrom = EpochBeginDate)THEN
472 CurrentFromDate := NULL;
473 ELSE
474 CurrentFromDate := TO_CHAR(inCurrentEffFrom, EffDateFormat);
475 END IF;
476
477 IF(inCurrentEffUntil = EpochEndDate)THEN
478 CurrentUntilDate := NULL;
479 ELSE
480 CurrentUntilDate := TO_CHAR(inCurrentEffUntil, EffDateFormat);
481 END IF;
482
483 vLogicLine := 'EFF ' || CurrentFromDate || ', ' || CurrentUntilDate || ', ' || vLogicLine || NewLine;
484
485 CurrentlyPacking := PACKING_EFFECTIVITY;
486 PACK_EFFECTIVITY;
487
488 PrevEffFrom := inCurrentEffFrom;
489 PrevEffUntil := inCurrentEffUntil;
490 PrevUsageMask := inCurrentUsageMask;
491 END IF;
492 END;
493 ---------------------------------------------------------------------------------------
494 --This procedure is used for marking BOM items that are ancestors of a trackable BOM
495 --item. Such items cannot have default quantity greater than 1, and cannot be on the
496 --RHS of a numeric rule.
497 --The procedure can be called only for a BOM Option Class or Standard or a reference,
498 --so parent always exists.
499
500 PROCEDURE PROPAGATE_TRACKABLE_ANCESTOR IS
501
502 auxIndex NUMBER := glIndexByPsNodeId(ntParentId(i)); --kdande; Bug 6881902; 11-Mar-2008
503 BEGIN
504 WHILE((NOT trackableAncestor.EXISTS(glPsNodeId(auxIndex))) AND
505 glPsNodeType(auxIndex) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))LOOP
506
507 IF(glInitialValue(auxIndex) > 1)THEN
508
509 nParam := auxIndex;
510 RAISE CZ_S_INCORRECT_QUANTITY;
511 END IF;
512
513 trackableAncestor(glPsNodeId(auxIndex)) := 1;
514 EXIT WHEN glParentId(auxIndex) IS NULL;
515
516 auxIndex := glIndexByPsNodeId(glParentId(auxIndex));
517 END LOOP;
518 END;
519 ---------------------------------------------------------------------------------------
520 FUNCTION IS_NODE_LOGICAL(j IN PLS_INTEGER) RETURN BOOLEAN IS
521 l_node_type NUMBER := ntPsNodeType(j);
522 BEGIN
523 RETURN
524 l_node_type <> PS_NODE_TYPE_TOTAL AND l_node_type <> PS_NODE_TYPE_RESOURCE AND
525 (l_node_type <> PS_NODE_TYPE_FEATURE OR
526 ntFeatureType(j) IN (PS_NODE_FEATURE_TYPE_BOOLEAN, PS_NODE_FEATURE_TYPE_OPTION) OR
527 (ntFeatureType(j) = PS_NODE_FEATURE_TYPE_INTEGER AND
528 ntMinimum(j) IS NOT NULL AND ntMinimum(j) >= 0));
529 END;
530 ---------------------------------------------------------------------------------------
531 PROCEDURE GENERATE_ACCUMULATOR(j IN PLS_INTEGER) IS
532 BEGIN
533
534 --Check if we need to create an accumulator for this node. Note that accumulator must be
535 --always effective. Part of the fix for the bug #2857955.
536
537 IF(ntAccumulator(j) IS NOT NULL AND ntAccumulator(j) <> FLAG_NO_ACCUMULATOR)THEN
538
539 GENERATE_EFFECTIVITY_LOGIC(EpochBeginDate, EpochEndDate, AnyUsageMask);
540 vLogicName := 'P_' || TO_CHAR(ntPersistentId(j));
541
542 IF((NOT v_HeaderByAccId.EXISTS(ntPsNodeId(j))) AND
543 TO_NUMBER(UTL_RAW.BIT_AND(ntAccumulator(j), FLAG_ACCUMULATOR_ACC)) = TO_NUMBER(FLAG_ACCUMULATOR_ACC))THEN
544
545 vLogicLine := 'TOTAL ' || vLogicName || '_ACC' || NewLine ||
546 'INC ' || vLogicName || '_ACC' || ' ' || vLogicName ||
547 OperatorLiterals(OPERATOR_ROUND) || NewLine;
548
549 v_HeaderByAccId(ntPsNodeId(j)) := nStructureHeaderId;
550 END IF;
551
552 IF((NOT v_HeaderByNotTrueId.EXISTS(ntPsNodeId(j))) AND
553 TO_NUMBER(UTL_RAW.BIT_AND(ntAccumulator(j), FLAG_ACCUMULATOR_NT)) = TO_NUMBER(FLAG_ACCUMULATOR_NT))THEN
554
555 --Bug #5015333. Only node that has a 'logical' value can have this type of accumulator. Initially the
556 --accumulator_flag may have been set by a NOTTRUE operator. At this time the node had to have logical
557 --value, otherwise the rule would have been rejected by a verification (HAS_LOGICAL_VALUE function in
558 --GENERATE_NOTTRUE procedure). However later the rule may have been deleted, and the type of the node
559 --changed, so that the node does not have a 'logical' value anymore. As the accumulator_flag is still
560 --set, the code below will create a 'logical' relation that may crash the engine.
561
562 IF(IS_NODE_LOGICAL(j))THEN
563
564 vLogicLine := 'OBJECT ' || vLogicName || '_NT' || NewLine ||
565 'NOTTRUE ' || vLogicName || ' ' || vLogicName || '_NT' || NewLine;
566 v_HeaderByNotTrueId(ntPsNodeId(j)) := nStructureHeaderId;
567
568 ELSE
569
570 --Although it is not necessary to reset the accumulator_flag here, doing so will allow to skip this
571 --verification in the future. This should not have any effect on the currency of the model's logic.
572
573 UPDATE cz_ps_nodes SET
574 accumulator_flag = TO_CHAR(TO_NUMBER(UTL_RAW.BIT_AND(ntAccumulator(j), FLAG_ACCUMULATOR_ACC)))
575 WHERE ps_node_id = ntPsNodeId(j);
576 END IF;
577 END IF;
578
579 PACK;
580 END IF;
581 END;
582 ---------------------------------------------------------------------------------------
583 PROCEDURE GENERATE_RULES IS
584
585 TYPE iteratorNode IS RECORD (node_type NUMBER,
586 node_id NUMBER,
587 node_value VARCHAR2(4000),
588 node_obj VARCHAR2(4000),
589 node_id_ex NUMBER);
590 TYPE tIteratorArray IS TABLE OF iteratorNode INDEX BY BINARY_INTEGER;
591
592 --The cursor returns all the rules assigned in this project (model).
593
594 CURSOR c_rules IS
595 SELECT rule_id, rule_type, antecedent_id, consequent_id, name, reason_id,
596 expr_rule_type, rule_folder_id, component_id, model_ref_expl_id,
597 effective_from, effective_until, effective_usage_mask, effectivity_set_id,
598 unsatisfied_msg_id, unsatisfied_msg_source, presentation_flag, class_name
599 FROM cz_rules
600 WHERE devl_project_id = inComponentId
601 AND deleted_flag = FLAG_NOT_DELETED
602 AND disabled_flag = FLAG_NOT_DISABLED;
603
604 v_tExplNodeId tExplNodeId;
605 v_tExprType tExprType;
606 v_tExprSubtype tExprSubtype;
607 v_tExprId tExprId;
608 v_tExprParentId tExprParentId;
609 v_tExprTemplateId tExprTemplateId;
610 v_tExprParamIndex tExprParamIndex;
611 v_tExprArgumentName tExprArgumentName;
612 v_tExprDataType tExprDataType;
613 v_tExpressId tExpressId;
614 v_tExprPsNodeId tExplNodeId;
615 v_tRealPsNodeId tExplNodeId;
616 v_tExprDataValue tExprDataValue;
617 v_tExprPropertyId tExprPropertyId;
618 v_tConsequentFlag tConsequentFlag;
619 v_tFeatureType tDesFeatureType;
620 v_tExprDataNumValue tExprDataNumValue;
621 v_tExprArgSignature tExprArgSignature;
622 v_tExprParSignature tExprParSignature;
623 v_LoadConditionId tExplNodeId;
624 v_ExplByPsNodeId tExplNodeId_idx_vc2; --kdande; Bug 6881902; 11-Mar-2008
625
626 v_tArgumentName tArgumentName;
627 v_tArgumentIndex tArgumentIndex;
628 v_tDataType tDataType;
629
630 v_InstByLevel tIntegerArray;
631 v_IndexByExprNodeId tIntegerArray_idx_vc2;
632 v_Assignable tIntegerArray;
633 v_Participant tIntegerArray;
634 v_DistinctIndex tIntegerArray;
635 v_ParticipantIndex tIntegerArray;
636 v_RuleConnectorNet tIntegerArray;
637 v_LevelCount tIntegerArray;
638 v_LevelIndex tIntegerArray;
639 v_LevelType tIntegerArray;
640 v_MarkLoadCondition tIntegerArray;
641 v_tIsHeaderGenerated tIntegerArray;
642 v_tSequenceNbr tIntegerArray;
643 v_tLogicNetType tIntegerArray;
644
645 v_NodeLogicLevel tIntegerArray;
646 v_NodeAssignable tIntegerArray;
647 v_NodeInstantiable tIntegerArray;
648 v_NodeTrackable tIntegerArray;
649 v_IsConnectorNet tIntegerArray;
650 v_ChildrenIndex tIntegerArray_idx_vc2;
651 v_NumberOfChildren tIntegerArray_idx_vc2;
652 v_MaxRuleExists tIntegerArray;
653 v_ProhibitInRules tIntegerArray;
654 v_ProhibitOptional tIntegerArray;
655 v_ProhibitConnector tIntegerArray;
656 v_NodeIndexPath tIntegerArray;
657 v_NodeDownPath tStringArray;
658 v_RelativeNodePath tStringArray;
659 v_AssignedDownPath tStringArray;
660 v_NodeUpPath tStringArray;
661 v_RuleQualifiedName tStringArray;
662 v_FuncQualifiedName tStringArray;
663
664 v_LoadHeaders tHeaderId;
665 v_LoadConditions tStringArray;
666
667 h_EffFrom tDateArray;
668 h_EffUntil tDateArray;
669 h_EffUsageMask tUsageMask;
670
671 PrevRuleEffFrom tDateArray;
672 PrevRuleEffUntil tDateArray;
673 PrevRuleUsageMask tUsageMask;
674
675 nAntecedentId cz_rules.antecedent_id%TYPE;
676 nConsequentId cz_rules.consequent_id%TYPE;
677 nRuleId cz_rules.rule_id%TYPE;
678 nRuleFolderId cz_rules.rule_folder_id%TYPE;
679 nRuleType cz_rules.rule_type%TYPE;
680 RuleTemplateType cz_rules.rule_type%TYPE;
681 nRuleOperator cz_rules.expr_rule_type%TYPE;
682 nReasonId cz_rules.reason_id%TYPE;
683 nComponentId cz_rules.component_id%TYPE;
684 nModelRefExplId cz_rules.model_ref_expl_id%TYPE;
685 dEffFrom cz_rules.effective_from%TYPE;
686 dEffUntil cz_rules.effective_until%TYPE;
687 nRuleEffSetId cz_rules.effectivity_set_id%TYPE;
688 nUnsatisfiedId cz_rules.unsatisfied_msg_id%TYPE;
689 nUnsatisfiedSource cz_rules.unsatisfied_msg_source%TYPE;
690 nPresentationFlag cz_rules.presentation_flag%TYPE;
691 vRuleName cz_rules.name%TYPE;
692 vUsageMask cz_rules.effective_usage_mask%TYPE;
693 vClassName cz_rules.class_name%TYPE;
694 MaxDepthId cz_model_ref_expls.model_ref_expl_id%TYPE;
695 nAux cz_model_ref_expls.model_ref_expl_id%TYPE;
696 MaxDepthValue cz_model_ref_expls.node_depth%TYPE;
697 baseDepthValue cz_model_ref_expls.node_depth%TYPE;
698 nHeaderId cz_lce_headers.lce_header_id%TYPE;
699 nPreviousHeaderId cz_lce_headers.lce_header_id%TYPE;
700 nNewLogicFileFlag PLS_INTEGER := 0;
701 nRuleAssignedLevel PLS_INTEGER;
702 MaxDepthIndex PLS_INTEGER;
703 logicNetType PLS_INTEGER;
704 expressionSize PLS_INTEGER;
705 expressionStart PLS_INTEGER;
706 expressionEnd PLS_INTEGER;
707 numericLHS PLS_INTEGER;
708 generateCompare PLS_INTEGER;
709 generateCollect PLS_INTEGER;
710
711 ConnectorIndex PLS_INTEGER;
712 InstantiableIndex PLS_INTEGER;
713 OptionalIndex PLS_INTEGER;
714 AssignableIndex PLS_INTEGER;
715 TrackableIndex PLS_INTEGER;
716
717 jAntecedentRoot PLS_INTEGER;
718 jConsequentRoot PLS_INTEGER;
719 jAntecedentRootCount PLS_INTEGER;
720 jConsequentRootCount PLS_INTEGER;
721 ListType PLS_INTEGER;
722 nLocalDefaults PLS_INTEGER := 0;
723 nLocalExprId PLS_INTEGER := 1000;
724
725 nCounter PLS_INTEGER;
726 distinctCount PLS_INTEGER;
727 participantCount PLS_INTEGER;
728 localFeatureType PLS_INTEGER;
729 localMinimum PLS_INTEGER;
730 auxIndex NUMBER; --kdande; Bug 6881902; 11-Mar-2008
731 auxCount NUMBER; --kdande; Bug 6881902; 11-Mar-2008
732 localString VARCHAR2(32000);
733 pathString VARCHAR2(32000);
734 baseString VARCHAR2(32000);
735 localNodeId NUMBER;
736 localRunId NUMBER;
737
738 generateRound PLS_INTEGER;
739 optimizeChain PLS_INTEGER;
740 optimizeContribute PLS_INTEGER;
741 optimizeTarget VARCHAR2(4000);
742 t_prefix VARCHAR2(128);
743
744 returnListType PLS_INTEGER;
745 returnStringArray tStringArray;
746
747 parameterScope tIteratorArray;
748 parameterName tStringArray;
749
750 --This type is used when it is necessary to hash a table name by a text key.
751
752 TYPE temp_table_hash_type IS TABLE OF VARCHAR2(30) INDEX BY VARCHAR2(4000);
753 temp_table_hash temp_table_hash_type;
754 temp_cmpt_table_hash temp_table_hash_type;
755
756 --Some of the variables are level specific for embedded FORALL, so we need to know the
757 --the current level. One example is the table hash key below.
758 --COMPATIBLE currently cannot be embedded, so the variable will never be greater than 1.
759
760 forallLevel PLS_INTEGER := 0;
761 compatLevel PLS_INTEGER := 0;
762
763 --This key is used to identify a temporary table constructed for an iterator and hash its
764 --name in temp_table_hash or temp_cmpt_table_hash.
765 --The format of this key is:
766 --<ps_node_id>-<model_ref_expl_id>-<property_id-1>-...-<property_id_N>
767
768 --We need tables of keys because of the possibility of embedded FORALL - on every level
769 --the level specific key should be considered.
770 --Although currently FORALL cannot be embedded into COMPATIBLE, this may change in the
771 --future, therefore it is better to have separate keys.
772
773 temp_table_hash_key tStringArray;
774 temp_cmpt_hash_key tStringArray;
775
776 --This is a universal array accumulating all the temp tables we need to delete across
777 --all FORALL(s) and COMPATIBLE(s).
778
779 temp_tables tStringArray;
780
781 --For logic and comparison rules having an unsatisified message (unsatisfied_msg_source <> 0)
782 --this string will be populated with unsatisfied_msg_id, and used as a part of GS syntax when
783 --the relation has more then one operand on either side. For all the other types of rules the
784 --string will be null.
785
786 sUnsatisfiedId VARCHAR2(4000);
787 ---------------------------------------------------------------------------------------
788 FUNCTION GET_PROPERTY_VALUE(p_node_id IN cz_ps_nodes.ps_node_id%TYPE,
789 p_property_id IN cz_properties.property_id%TYPE,
790 p_item_id IN cz_item_masters.item_id%TYPE,
791 x_data_type IN OUT NOCOPY cz_properties.data_type%TYPE)
792 RETURN VARCHAR2 IS
793 l_def_value cz_properties.def_value%TYPE;
794 l_tab tStringArray;
795 BEGIN
796
797 SELECT NVL(TO_CHAR(def_num_value), def_value), data_type INTO l_def_value, x_data_type
798 FROM cz_properties
799 WHERE property_id = p_property_id
800 AND deleted_flag = FLAG_NOT_DELETED;
801
802 SELECT NVL(TO_CHAR(data_num_value), data_value) BULK COLLECT INTO l_tab
803 FROM cz_ps_prop_vals
804 WHERE ps_node_id = p_node_id
805 AND property_id = p_property_id
806 AND deleted_flag = FLAG_NOT_DELETED;
807
808 IF(l_tab.COUNT = 0 AND p_item_id IS NOT NULL)THEN
809
810 SELECT NVL(TO_CHAR(property_num_value), property_value) BULK COLLECT INTO l_tab
811 FROM cz_item_property_values
812 WHERE property_id = p_property_id
813 AND item_id = p_item_id
814 AND deleted_flag = FLAG_NOT_DELETED;
815
816 IF(l_tab.COUNT = 0)THEN
817
818 SELECT NULL BULK COLLECT INTO l_tab
819 FROM cz_item_type_properties t, cz_item_masters m
820 WHERE m.item_id = p_item_id
821 AND m.deleted_flag = FLAG_NOT_DELETED
822 AND t.deleted_flag = FLAG_NOT_DELETED
823 AND t.property_id = p_property_id
824 AND t.item_type_id = m.item_type_id;
825 END IF;
826 END IF;
827
828 IF(l_tab.EXISTS(1))THEN
829
830 IF(x_data_type = DATATYPE_TRANSLATABLE_PROP)THEN
831
832 SELECT localized_str INTO l_tab(1) FROM cz_localized_texts
833 WHERE intl_text_id = l_tab(1) AND language = USERENV('LANG');
834
835 IF(l_tab(1) IS NULL)THEN
836
837 SELECT localized_str INTO l_tab(1) FROM cz_localized_texts
838 WHERE intl_text_id = l_def_value AND language = USERENV('LANG');
839 END IF;
840 END IF;
841
842 RETURN NVL(l_tab(1), l_def_value);
843 END IF;
844
845 x_data_type := NULL;
846 RETURN NULL;
847
848 EXCEPTION
849 WHEN NO_DATA_FOUND THEN
850 x_data_type := NULL;
851 RETURN NULL;
852 END;
853 ---------------------------------------------------------------------------------------
854 --The local procedure is required because the sequence numbers must be different
855 --Still works with global buffers and commit parameters
856
857 PROCEDURE PACK IS
858 BEGIN
859 IF(vLogicLine IS NOT NULL)THEN
860 IF(LENGTHB(vLogicText) + LENGTHB(vLogicLine)>2000)THEN
861
862 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
863 (nHeaderId, v_tSequenceNbr(nHeaderId), vLogicText);
864 vLogicText := NULL;
865 v_tSequenceNbr(nHeaderId) := v_tSequenceNbr(nHeaderId) + 1;
866
867 --Commit in blocks if not disabled
868
869 IF(TwoPhaseCommit = 0)THEN
870 commit_counter := commit_counter + 1;
871 IF(commit_counter = CommitBlockSize)THEN
872 COMMIT;
873 commit_counter := 0;
874 END IF;
875 END IF;
876 END IF;
877 vLogicText := vLogicText || vLogicLine;
878 vLogicLine := NULL;
879 END IF;
880 END PACK;
881 ---------------------------------------------------------------------------------------
882 --This function returns fully qualified rule name given rule_folder_id of a rule
883 --and puts generated names into a hash table for reuse.
884
885 FUNCTION RULE_NAME RETURN VARCHAR2 IS
886 vQualified VARCHAR2(4000) := '.';
887 nRuleName PLS_INTEGER;
888 BEGIN
889 IF(nRuleFolderId IS NULL OR nRuleFolderId = -1)THEN RETURN vRuleName; END IF;
890 IF(v_RuleQualifiedName.EXISTS(nRuleFolderId))THEN RETURN v_RuleQualifiedName(nRuleFolderId) || vRuleName; END IF;
891 nRuleName := LENGTHB(vRuleName);
892 FOR folder IN (SELECT name FROM cz_rule_folders
893 WHERE deleted_flag = FLAG_NOT_DELETED
894 AND parent_rule_folder_id IS NOT NULL
895 START WITH rule_folder_id = nRuleFolderId
896 AND object_type = 'RFL'
897 CONNECT BY PRIOR parent_rule_folder_id = rule_folder_id
898 AND object_type = 'RFL')LOOP
899 IF(LENGTHB(folder.name) + LENGTHB(vQualified) + 1 < 2000 - nRuleName)THEN
900 vQualified := '.' || folder.name || vQualified;
901 ELSE
902 EXIT;
903 END IF;
904 END LOOP;
905 v_RuleQualifiedName(nRuleFolderId) := vQualified;
906 RETURN vQualified || vRuleName;
907 END;
908 ---------------------------------------------------------------------------------------
909 --This function returns fully qualified name of a functional companion given
910 --rule_folder_id.
911
912 FUNCTION COMPANION_NAME(inCompanionName IN VARCHAR2, inFolderId IN NUMBER) RETURN VARCHAR2 IS
913 vQualified VARCHAR2(4000) := '.';
914 nameLen PLS_INTEGER;
915 BEGIN
916 IF(inFolderId IS NULL OR inFolderId = -1)THEN RETURN inCompanionName; END IF;
917 IF(v_FuncQualifiedName.EXISTS(inFolderId))THEN RETURN v_FuncQualifiedName(inFolderId) || inCompanionName; END IF;
918 nameLen := LENGTHB(inCompanionName);
919 FOR folder IN (SELECT name FROM cz_rule_folders
920 WHERE deleted_flag = FLAG_NOT_DELETED
921 AND parent_rule_folder_id IS NOT NULL
922 START WITH rule_folder_id = inFolderId
923 CONNECT BY PRIOR parent_rule_folder_id = rule_folder_id)LOOP
924 IF(LENGTHB(folder.name) + LENGTHB(vQualified) + 1 < 2000 - nameLen)THEN
925 vQualified := '.' || folder.name || vQualified;
926 ELSE
927 EXIT;
928 END IF;
929 END LOOP;
930 v_FuncQualifiedName(inFolderId) := vQualified;
931 RETURN vQualified || inCompanionName;
932 END;
933 ---------------------------------------------------------------------------------------
934 --The ps_node_id value is fixed in the memory for references to BOM. This function can
935 --be called when the original value (ps_node_id of the reference node) is required.
936
937 FUNCTION REAL_PS_NODE_ID(j IN PLS_INTEGER) RETURN NUMBER IS
938 BEGIN
939 IF(v_tRealPsNodeId.EXISTS(j))THEN RETURN v_tRealPsNodeId(j); ELSE RETURN v_tExprPsNodeId(j); END IF;
940 END;
941 ---------------------------------------------------------------------------------------
942 FUNCTION SIGNATURE_DATA_TYPE(p_signature_id IN NUMBER) RETURN PLS_INTEGER IS
943 v_data_type PLS_INTEGER;
944 BEGIN
945 IF(h_SignatureDataType.EXISTS(p_signature_id))THEN RETURN h_SignatureDataType(p_signature_id); END IF;
946
947 BEGIN
948 SELECT data_type INTO v_data_type FROM cz_signatures
949 WHERE deleted_flag = FLAG_NOT_DELETED
950 AND signature_id = p_signature_id;
951
952 h_SignatureDataType(p_signature_id) := v_data_type;
953 RETURN v_data_type;
954 EXCEPTION
955 WHEN OTHERS THEN
956 RAISE CZ_R_NO_SIGNATURE_ID;
957 END;
958 END;
959 ---------------------------------------------------------------------------------------
960 FUNCTION COMPATIBLE_DATA_TYPES(p_object_type IN PLS_INTEGER, p_subject_type PLS_INTEGER) RETURN BOOLEAN IS
961 v_null PLS_INTEGER;
962 BEGIN
963 SELECT NULL INTO v_null FROM cz_conversion_rels_v
964 WHERE object_type = p_object_type AND subject_type = p_subject_type;
965 RETURN TRUE;
966 EXCEPTION
967 WHEN NO_DATA_FOUND THEN
968 RETURN FALSE;
969 WHEN TOO_MANY_ROWS THEN
970 RETURN TRUE;
971 WHEN OTHERS THEN
972 RETURN FALSE;
973 END;
974 ---------------------------------------------------------------------------------------
975 FUNCTION GET_ARGUMENT_INFO(p_param_index IN NUMBER,
976 p_signature_id IN NUMBER,
977 x_mutable IN OUT NOCOPY VARCHAR2,
978 x_collection IN OUT NOCOPY VARCHAR2)
979 RETURN NUMBER IS
980 v_data_type cz_signature_arguments.data_type%TYPE;
981 BEGIN
982 SELECT data_type, mutable_flag, collection_flag INTO v_data_type, x_mutable, x_collection
983 FROM cz_signature_arguments
984 WHERE deleted_flag = FLAG_NOT_DELETED
985 AND argument_signature_id = p_signature_id
986 AND argument_index = p_param_index;
987 RETURN v_data_type;
988 EXCEPTION
989 WHEN OTHERS THEN
990 RETURN DATA_TYPE_VOID;
991 END;
992 ---------------------------------------------------------------------------------------
993 FUNCTION APPLICABLE_SYS_PROP(j IN PLS_INTEGER, p_ps_node_id IN NUMBER, p_rule_id IN NUMBER) RETURN BOOLEAN IS
994 v_null PLS_INTEGER;
995 v_ps_node_id NUMBER;
996 v_data_type cz_signature_arguments.data_type%TYPE;
997 v_mutable cz_signature_arguments.mutable_flag%TYPE;
998 v_collection cz_signature_arguments.collection_flag%TYPE;
999 BEGIN
1000
1001 --Some of the upgraded rules may not have param_index and param_signature_id populated. However, upgraded
1002 --rules are not real statement rules, so they are not supposed to have any user error in them and in this
1003 --case the verification is not required.
1004
1005 IF(v_tExprParamIndex(j) IS NULL OR v_tExprParSignature(j) IS NULL)THEN RETURN TRUE; END IF;
1006
1007 IF(p_ps_node_id IS NULL)THEN v_ps_node_id := REAL_PS_NODE_ID(j); ELSE v_ps_node_id := p_ps_node_id; END IF;
1008 v_data_type := GET_ARGUMENT_INFO(v_tExprParamIndex(j), v_tExprParSignature(j), v_mutable, v_collection);
1009
1010 SELECT NULL INTO v_null
1011 FROM cz_rul_typedpsn_v psn,
1012 cz_conversion_rels_v cnv,
1013 cz_system_property_rels_v rel,
1014 cz_system_properties_v sys,
1015 cz_conversion_rels_v cnv2
1016 WHERE psn.detailed_type_id = cnv.object_type
1017 AND cnv.subject_type = rel.subject_type
1018 AND rel.object_type = sys.rule_id
1019 AND rel.rel_type_code = 'SYS'
1020 AND sys.data_type = cnv2.object_type
1021 AND psn.ps_node_id = v_ps_node_id
1022 AND sys.rule_id = p_rule_id
1023 AND sys.mutable_flag >= v_mutable
1024 AND sys.collection_flag <= v_collection
1025 AND cnv2.subject_type = v_data_type;
1026
1027 RETURN TRUE;
1028 EXCEPTION
1029 WHEN NO_DATA_FOUND THEN
1030 RETURN FALSE;
1031 WHEN TOO_MANY_ROWS THEN
1032 RETURN TRUE;
1033 WHEN OTHERS THEN
1034 RETURN FALSE;
1035 END;
1036 ---------------------------------------------------------------------------------------
1037 FUNCTION APPLICABLE_SYS_PROP(j IN PLS_INTEGER, p_ps_node_id IN NUMBER, p_rule_name IN VARCHAR2) RETURN BOOLEAN IS
1038 v_null PLS_INTEGER;
1039 v_ps_node_id NUMBER;
1040 v_data_type cz_signature_arguments.data_type%TYPE;
1041 v_mutable cz_signature_arguments.mutable_flag%TYPE;
1042 v_collection cz_signature_arguments.collection_flag%TYPE;
1043 BEGIN
1044
1045 --Some of the upgraded rules may not have param_index and param_signature_id populated. However, upgraded
1046 --rules are not real statement rules, so they are not supposed to have any user error in them and in this
1047 --case the verification is not required.
1048
1049 IF(v_tExprParamIndex(j) IS NULL OR v_tExprParSignature(j) IS NULL)THEN RETURN TRUE; END IF;
1050
1051 IF(p_ps_node_id IS NULL)THEN v_ps_node_id := REAL_PS_NODE_ID(j); ELSE v_ps_node_id := p_ps_node_id; END IF;
1052 v_data_type := GET_ARGUMENT_INFO(v_tExprParamIndex(j), v_tExprParSignature(j), v_mutable, v_collection);
1053
1054 SELECT NULL INTO v_null
1055 FROM cz_rul_typedpsn_v psn,
1056 cz_conversion_rels_v cnv,
1057 cz_system_property_rels_v rel,
1058 cz_system_properties_v sys,
1059 cz_conversion_rels_v cnv2
1060 WHERE psn.detailed_type_id = cnv.object_type
1061 AND cnv.subject_type = rel.subject_type
1062 AND rel.object_type = sys.rule_id
1063 AND rel.rel_type_code = 'SYS'
1064 AND sys.data_type = cnv2.object_type
1065 AND psn.ps_node_id = v_ps_node_id
1066 AND UPPER(sys.name) = p_rule_name
1067 AND sys.mutable_flag >= v_mutable
1068 AND sys.collection_flag <= v_collection
1069 AND cnv2.subject_type = v_data_type;
1070
1071 RETURN TRUE;
1072 EXCEPTION
1073 WHEN NO_DATA_FOUND THEN
1074 RETURN FALSE;
1075 WHEN TOO_MANY_ROWS THEN
1076 RETURN TRUE;
1077 WHEN OTHERS THEN
1078 RETURN FALSE;
1079 END;
1080 ---------------------------------------------------------------------------------------
1081 --Splits the CHR(7)-separated path into an array of node names.
1082
1083 FUNCTION SPLIT_PATH(p_path IN VARCHAR2) RETURN tStringArray IS
1084
1085 l_substr VARCHAR2(32000) := p_path;
1086 l_index PLS_INTEGER;
1087 l_return_tbl tStringArray;
1088 BEGIN
1089
1090 IF(p_path IS NULL)THEN RETURN l_return_tbl; END IF;
1091 LOOP
1092
1093 l_index := INSTR(l_substr, FND_GLOBAL.LOCAL_CHR(7));
1094
1095 IF(l_index > 0)THEN
1096
1097 l_return_tbl(l_return_tbl.COUNT + 1) := SUBSTR(l_substr, 1, l_index - 1);
1098 l_substr := SUBSTR(l_substr, l_index + 1);
1099 ELSE
1100
1101 l_return_tbl(l_return_tbl.COUNT + 1) := l_substr;
1102 EXIT;
1103 END IF;
1104 END LOOP;
1105
1106 RETURN l_return_tbl;
1107 END;
1108 ---------------------------------------------------------------------------------------
1109 PROCEDURE RESOLVE_NODE(p_node_tbl IN tStringArray,
1110 p_parent_node_id IN NUMBER,
1111 p_parent_expl_id IN NUMBER,
1112 x_child_node_id IN OUT NOCOPY NUMBER,
1113 x_child_expl_id IN OUT NOCOPY NUMBER) IS
1114
1115 l_eff_from DATE := EpochBeginDate;
1116 l_eff_until DATE := EpochEndDate;
1117 l_index PLS_INTEGER;
1118 l_parent_id NUMBER;
1119
1120 l_return_node_id_tbl tNumberArray;
1121 l_return_expl_id_tbl tNumberArray;
1122
1123 FUNCTION REPORT_PATH RETURN VARCHAR2 IS
1124
1125 l_return VARCHAR2(32000) := NULL;
1126 BEGIN
1127
1128 FOR i IN 1..p_node_tbl.COUNT LOOP
1129
1130 IF(l_return IS NOT NULL)THEN l_return := l_return || '.'; END IF;
1131 l_return := l_return || p_node_tbl(i);
1132 END LOOP;
1133 RETURN l_return;
1134 END;
1135
1136 PROCEDURE RESOLVE_CHILDREN(p_index IN PLS_INTEGER,
1137 p_node_id IN NUMBER,
1138 p_expl_id IN NUMBER,
1139 p_eff_from IN DATE,
1140 p_eff_until IN DATE) IS
1141
1142 t_eff_from_tbl tDateArray;
1143 t_eff_until_tbl tDateArray;
1144 t_node_id_tbl tNumberArray;
1145 t_expl_id_tbl tNumberArray;
1146 l_eff_from_tbl tDateArray;
1147 l_eff_until_tbl tDateArray;
1148 l_node_id_tbl tNumberArray;
1149 l_expl_id_tbl tNumberArray;
1150
1151 l_counter PLS_INTEGER := 0;
1152 l_index PLS_INTEGER;
1153 BEGIN
1154
1155 SELECT ps_node_id, model_ref_expl_id, effective_from, effective_until
1156 BULK COLLECT INTO l_node_id_tbl, l_expl_id_tbl, l_eff_from_tbl, l_eff_until_tbl
1157 FROM cz_explmodel_nodes_v
1158 WHERE model_id = inComponentId
1159 AND parent_psnode_expl_id = p_expl_id
1160 AND effective_parent_id = p_node_id
1161 AND suppress_flag = '0'
1162 AND name = p_node_tbl(p_index);
1163
1164 FOR i IN 1..l_node_id_tbl.COUNT LOOP
1165
1166 IF(p_eff_from > l_eff_from_tbl(i))THEN l_eff_from_tbl(i) := p_eff_from; END IF;
1167 IF(p_eff_until < l_eff_until_tbl(i))THEN l_eff_until_tbl(i) := p_eff_until; END IF;
1168
1169 IF(l_eff_from_tbl(i) <= l_eff_until_tbl(i))THEN
1170
1171 l_counter := l_counter + 1;
1172
1173 t_eff_from_tbl(l_counter) := l_eff_from_tbl(i);
1174 t_eff_until_tbl(l_counter) := l_eff_until_tbl(i);
1175 t_node_id_tbl(l_counter) := l_node_id_tbl(i);
1176 t_expl_id_tbl(l_counter) := l_expl_id_tbl(i);
1177 END IF;
1178 END LOOP;
1179
1180 FOR i IN 1..t_node_id_tbl.COUNT LOOP
1181
1182 IF(p_index = p_node_tbl.COUNT)THEN
1183
1184 l_index := l_return_node_id_tbl.COUNT + 1;
1185
1186 l_return_node_id_tbl(l_index) := t_node_id_tbl(i);
1187 l_return_expl_id_tbl(l_index) := t_expl_id_tbl(i);
1188 ELSE
1189
1190 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));
1191 END IF;
1192 END LOOP;
1193 END;
1194 BEGIN
1195
1196 --Propagate effectivity from all the bom references down from the root model.
1197
1198 FOR i IN 1..globalLevel LOOP
1199
1200 --We need to stop on the model, in which the rule is defined.
1201
1202 IF(globalStack(i) = inComponentId)THEN EXIT; END IF;
1203
1204 --Account only for references to bom(s).
1205
1206 IF(glPsNodeType(glIndexByPsNodeId(globalStack(i))) IN (PS_NODE_TYPE_BOM_MODEL,PS_NODE_TYPE_BOM_OPTIONCLASS,PS_NODE_TYPE_BOM_STANDARD))THEN
1207
1208 l_index := glIndexByPsNodeId(globalRef(i));
1209
1210 IF(glEffFrom(l_index) > l_eff_from)THEN l_eff_from := glEffFrom(l_index); END IF;
1211 IF(glEffUntil(l_index) < l_eff_until)THEN l_eff_until := glEffUntil(l_index); END IF;
1212 END IF;
1213 END LOOP;
1214
1215 --Adjust effectivities for the least unambiguous parent.
1216
1217 l_index := glIndexByPsNodeId(p_parent_node_id);
1218
1219 IF(glEffFrom(l_index) > l_eff_from)THEN l_eff_from := glEffFrom(l_index); END IF;
1220 IF(glEffUntil(l_index) < l_eff_until)THEN l_eff_until := glEffUntil(l_index); END IF;
1221
1222 --Finally adjust for the rule effectivity.
1223
1224 IF(dEffFrom > l_eff_from)THEN l_eff_from := dEffFrom; END IF;
1225 IF(dEffUntil < l_eff_until)THEN l_eff_until := dEffUntil; END IF;
1226
1227 --If effectivity range is empty, it will be impossible to resolve the node.
1228
1229 IF(l_eff_until < l_eff_from)THEN
1230
1231 localString := REPORT_PATH;
1232 RAISE CZ_R_INCORRECT_REFERENCE;
1233 END IF;
1234
1235 IF(p_node_tbl.COUNT = 0)THEN
1236
1237 x_child_node_id := p_parent_node_id;
1238 x_child_expl_id := p_parent_expl_id;
1239 RETURN;
1240 END IF;
1241
1242 RESOLVE_CHILDREN(1, p_parent_node_id, p_parent_expl_id, l_eff_from, l_eff_until);
1243
1244 IF(l_return_node_id_tbl.COUNT = 0)THEN
1245
1246 localString := REPORT_PATH;
1247 RAISE CZ_R_INCORRECT_REFERENCE;
1248 ELSIF(l_return_node_id_tbl.COUNT > 1)THEN
1249
1250 localString := REPORT_PATH;
1251 RAISE CZ_R_AMBIGUOUS_REFERENCE;
1252 ELSE
1253
1254 x_child_node_id := l_return_node_id_tbl(1);
1255 x_child_expl_id := l_return_expl_id_tbl(1);
1256 END IF;
1257 END;
1258 ---------------------------------------------------------------------------------------
1259 --Forward declarations block.
1260
1261 FUNCTION GENERATE_EXPRESSION(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray;
1262 FUNCTION GENERATE_REFNODE(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray;
1263 FUNCTION LOOKUP_ARGUMENT(j IN PLS_INTEGER) RETURN PLS_INTEGER;
1264 FUNCTION GENERATE_ARGUMENT(j IN PLS_INTEGER, ListType IN OUT NOCOPY PLS_INTEGER) RETURN tStringArray;
1265 ---------------------------------------------------------------------------------------
1266 FUNCTION HAS_LOGICAL_VALUE(j IN PLS_INTEGER) RETURN BOOLEAN IS
1267 NodeType PLS_INTEGER := v_tExprType(j);
1268 PsNodeType PLS_INTEGER;
1269 PsNodeIndex PLS_INTEGER;
1270 BEGIN
1271
1272 --When the validation is made from the high-level section of a logic rule, some of the participants
1273 --may still be arguments, so we need to look up the value of the argument before validating its
1274 --type. The argument in this case can be either a literal or a node (bug #3388169).
1275
1276 IF(NodeType = EXPR_ARGUMENT)THEN
1277
1278 PsNodeIndex := LOOKUP_ARGUMENT(j);
1279 IF(parameterScope(PsNodeIndex).node_id IS NULL)THEN RETURN FALSE; END IF;
1280
1281 NodeType := EXPR_PSNODE;
1282 v_tExprPsNodeId(j) := parameterScope(PsNodeIndex).node_id;
1283 END IF;
1284
1285 IF(NodeType = EXPR_NODE_TYPE_LITERAL)THEN
1286 RETURN (v_tExprDataType(j) = DATA_TYPE_BOOLEAN);
1287 ELSIF(NodeType = EXPR_PSNODE)THEN
1288 IF(v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN RETURN TRUE;
1289 ELSE
1290
1291 PsNodeIndex := glIndexByPsNodeId(v_tExprPsNodeId(j));
1292 PsNodeType := glPsNodeType(PsNodeIndex);
1293
1294 RETURN
1295 PsNodeType <> PS_NODE_TYPE_TOTAL
1296 AND
1297 PsNodeType <> PS_NODE_TYPE_RESOURCE
1298 AND
1299 (
1300 PsNodeType <> PS_NODE_TYPE_FEATURE
1301 OR
1302 glFeatureType(PsNodeIndex) IN (PS_NODE_FEATURE_TYPE_BOOLEAN, PS_NODE_FEATURE_TYPE_OPTION)
1303 OR
1304 (
1305 glFeatureType(PsNodeIndex) = PS_NODE_FEATURE_TYPE_INTEGER
1306 AND
1307 glMinimum(PsNodeIndex) IS NOT NULL
1308 AND
1309 glMinimum(PsNodeIndex) >= 0
1310 )
1311 );
1312 END IF;
1313 ELSIF(NodeType = EXPR_NODE_TYPE_OPERATOR)THEN
1314 RETURN COMPATIBLE_DATA_TYPES(SIGNATURE_DATA_TYPE(h_SignatureId(v_tExprSubtype(j))), DATA_TYPE_BOOLEAN);
1315 ELSIF(NodeType IN (EXPR_FORALL, EXPR_FORALL_DISTINCT))THEN
1316 RETURN TRUE;
1317 ELSE
1318 RETURN FALSE;
1319 END IF;
1320 END;
1321 ---------------------------------------------------------------------------------------
1322 FUNCTION HAS_OPTIONS_APPLIED(j IN PLS_INTEGER) RETURN BOOLEAN IS
1323 BEGIN
1324 RETURN (v_ChildrenIndex.EXISTS(v_tExprId(j)) AND
1325 h_SeededName.EXISTS(v_tExprSubtype(v_ChildrenIndex(v_tExprId(j)))) AND
1326 h_SeededName(v_tExprSubtype(v_ChildrenIndex(v_tExprId(j)))) = RULE_SYS_PROP_OPTIONS);
1327 END;
1328 ---------------------------------------------------------------------------------------
1329 FUNCTION GENERATE_NODE_CHILDREN(j IN PLS_INTEGER) RETURN tStringArray IS
1330 v_return tStringArray;
1331 nChild PLS_INTEGER;
1332 nCount PLS_INTEGER;
1333 oper tStringArray;
1334 ListType PLS_INTEGER;
1335 BEGIN
1336
1337 --nDebug := 7000005;
1338
1339 nCount := 1;
1340 nChild := v_ChildrenIndex(v_tExprId(j));
1341
1342 --nDebug := 7000006;
1343
1344 WHILE(v_tExprParentId(nChild) = v_tExprId(j)) LOOP
1345
1346 --nDebug := 7000007;
1347
1348 oper.DELETE;
1349 oper := GENERATE_EXPRESSION(nChild, ListType);
1350
1351 FOR i IN 1..oper.COUNT LOOP
1352
1353 v_return(nCount) := oper(i);
1354 nCount := nCount + 1;
1355
1356 END LOOP;
1357
1358 nChild := nChild + 1;
1359
1360 END LOOP;
1361
1362 --nDebug := 7000008;
1363
1364 RETURN v_return;
1365 END;
1366 ---------------------------------------------------------------------------------------
1367 FUNCTION GENERATE_NAME(j IN PLS_INTEGER, id IN NUMBER) RETURN VARCHAR2 IS --kdande; Bug 6881902; 11-Mar-2008
1368 v_return VARCHAR2(4000);
1369 counter PLS_INTEGER;
1370 val PLS_INTEGER;
1371 delimiter CHAR(1) := NULL;
1372 ExplId cz_model_ref_expls.model_ref_expl_id%TYPE := v_tExplNodeId(j);
1373 BEGIN
1374
1375 IF(NOT v_NodeUpPath.EXISTS(ExplId))THEN
1376 counter := nRuleAssignedLevel;
1377 val := v_NodeLogicLevel(ExplId);
1378 WHILE(counter > val) LOOP
1379 v_return := v_return || PATH_DELIMITER || 'parent';
1380 counter := counter - 1;
1381 END LOOP;
1382 v_NodeUpPath(ExplId) := v_return;
1383 ELSE
1384 v_return := v_NodeUpPath(ExplId);
1385 END IF;
1386
1387 IF(v_tLogicNetType(nHeaderId) = LOGIC_NET_TYPE_NETWORK AND (NOT v_IsConnectorNet.EXISTS(ExplId)))THEN
1388
1389 --If we are generating into a conditional net, we add an extra ^parent to the path, but only if
1390 --this is not a connector's net.
1391
1392 v_return := PATH_DELIMITER || 'parent' || v_return;
1393 END IF;
1394
1395 IF(v_return IS NOT NULL OR v_AssignedDownPath(ExplId) IS NOT NULL)THEN
1396 delimiter := PATH_DELIMITER;
1397 END IF;
1398
1399 v_return := v_return || v_AssignedDownPath(ExplId) || delimiter;
1400
1401 --The description below is only true if the reference participates in the rule as an
1402 --object, because if this is a rule against this reference's system property than we
1403 --still should generate the regular name. So, we need to make sure that we construct
1404 --the new name only if this reference participates in compatibility rules - the only
1405 --type of rules where it can participate as an object (an option). Bug #2567898.
1406
1407 IF(nRuleType IN (RULE_TYPE_COMPAT_RULE, RULE_TYPE_COMPAT_TABLE, RULE_TYPE_DESIGNCHART_RULE) AND
1408 glPsNodeType(glIndexByPsNodeId(id)) = PS_NODE_TYPE_REFERENCE)THEN
1409
1410 --The following comment is not exactly correct, see the above description.
1411 --The node identified by <id> is a reference. In this case we should not generate
1412 --the regular P_<id>, because such object would never exist. Instead, we generate
1413 --^N_<id>^P_<reference_id> to refer to the referenced object in the child subnet.
1414 --This fixes the base bug #2128641.
1415
1416 IF(v_return IS NULL)THEN v_return := PATH_DELIMITER; END IF;
1417 v_return := v_return || 'N_' || TO_CHAR(glPersistentId(id)) || PATH_DELIMITER ||
1418 'P_' || TO_CHAR(glReferenceId(id));
1419 ELSE
1420
1421 v_return := v_return || 'P_' || TO_CHAR(glPersistentId(id));
1422 END IF;
1423
1424 RETURN v_return;
1425 END;
1426 ---------------------------------------------------------------------------------------
1427 --Special version of GENERATE_NAME that accepts model_ref_expl_id value as a parameter
1428 --instead of extracting it from cz_expression nodes by index j.
1429
1430 FUNCTION GENERATE_NAME_EXPL(ExplId IN PLS_INTEGER, id IN NUMBER) RETURN VARCHAR2 IS --kdande; Bug 6881902; 11-Mar-2008
1431 v_return VARCHAR2(4000);
1432 counter PLS_INTEGER;
1433 val PLS_INTEGER;
1434 delimiter CHAR(1) := NULL;
1435 BEGIN
1436
1437 IF(NOT v_NodeUpPath.EXISTS(ExplId))THEN
1438 counter := nRuleAssignedLevel;
1439 val := v_NodeLogicLevel(ExplId);
1440 WHILE(counter > val) LOOP
1441 v_return := v_return || PATH_DELIMITER || 'parent';
1442 counter := counter - 1;
1443 END LOOP;
1444 v_NodeUpPath(ExplId) := v_return;
1445 ELSE
1446 v_return := v_NodeUpPath(ExplId);
1447 END IF;
1448
1449 IF(v_tLogicNetType(nHeaderId) = LOGIC_NET_TYPE_NETWORK AND (NOT v_IsConnectorNet.EXISTS(ExplId)))THEN
1450
1451 --If we are generating into a conditional net, we add an extra ^parent to the path, but only if
1452 --this is not a connector's net.
1453
1454 v_return := PATH_DELIMITER || 'parent' || v_return;
1455 END IF;
1456
1457 IF(v_return IS NOT NULL OR v_AssignedDownPath(ExplId) IS NOT NULL)THEN
1458 delimiter := PATH_DELIMITER;
1459 END IF;
1460
1461 v_return := v_return || v_AssignedDownPath(ExplId) || delimiter;
1462
1463 --The description below is only true if the reference participates in the rule as an
1464 --object, because if this is a rule against this reference's system property than we
1465 --still should generate the regular name. So, we need to make sure that we construct
1466 --the new name only if this reference participates in compatibility rules - the only
1467 --type of rules where it can participate as an object (an option). Bug #2567898.
1468
1469 IF(nRuleType IN (RULE_TYPE_COMPAT_RULE, RULE_TYPE_COMPAT_TABLE, RULE_TYPE_DESIGNCHART_RULE) AND
1470 glPsNodeType(glIndexByPsNodeId(id)) = PS_NODE_TYPE_REFERENCE)THEN
1471
1472 --The following comment is not exactly correct, see the above description.
1473 --The node identified by <id> is a reference. In this case we should not generate
1474 --the regular P_<id>, because such object would never exist. Instead, we generate
1475 --^N_<id>^P_<reference_id> to refer to the referenced object in the child subnet.
1476 --This fixes the base bug #2128641.
1477
1478 IF(v_return IS NULL)THEN v_return := PATH_DELIMITER; END IF;
1479 v_return := v_return || 'N_' || TO_CHAR(glPersistentId(id)) || PATH_DELIMITER ||
1480 'P_' || TO_CHAR(glReferenceId(id));
1481 ELSE
1482
1483 v_return := v_return || 'P_' || TO_CHAR(glPersistentId(id));
1484 END IF;
1485
1486 RETURN v_return;
1487 END;
1488 ---------------------------------------------------------------------------------------
1489 FUNCTION GENERATE_NODE(j IN PLS_INTEGER) RETURN tStringArray IS
1490 v_return tStringArray;
1491 BEGIN
1492
1493 v_return(1) := GENERATE_NAME(j, v_tExprPsNodeId(j));
1494 RETURN v_return;
1495
1496 END;
1497 ---------------------------------------------------------------------------------------
1498 FUNCTION ADJUSTED_EXPLOSION(p_parent_expl_id IN NUMBER, p_child_node_id IN NUMBER) RETURN NUMBER IS
1499 BEGIN
1500 FOR i IN 1..v_NodeId.COUNT LOOP
1501 IF(v_tParentId(i) = p_parent_expl_id AND v_tReferringId(i) = p_child_node_id)THEN
1502 RETURN v_NodeId(i);
1503 END IF;
1504 END LOOP;
1505 END;
1506 ---------------------------------------------------------------------------------------
1507 FUNCTION EXPAND_NODE(j IN PLS_INTEGER) RETURN tIntegerArray IS
1508 v_result tIntegerArray;
1509 nCount PLS_INTEGER;
1510 v_ps_node_id NUMBER; --kdande; Bug 6881902; 11-Mar-2008
1511 v_node_type PLS_INTEGER;
1512 v_index PLS_INTEGER;
1513 v_start_index PLS_INTEGER;
1514 v_end_index PLS_INTEGER;
1515 BEGIN
1516
1517 IF(v_tExprType(j) = EXPR_OPERATOR)THEN
1518
1519 --The function is called on an operator node. We assume that this is OptionsOf, and so it has one
1520 --operand which represents a structure node. This structure node has its explosion populated in
1521 --cz_expression_nodes table. It is often convenient to associate this explosion also with the
1522 --operator itself. This is a fix for the bug #2232741.
1523
1524 v_ps_node_id := v_tExprPsNodeId(v_ChildrenIndex(v_tExprId(j)));
1525 v_tExplNodeId(j) := v_tExplNodeId(v_ChildrenIndex(v_tExprId(j)));
1526
1527 ELSIF(v_tExprType(j) = EXPR_PSNODE AND v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
1528
1529 v_ps_node_id := v_tExprPsNodeId(j);
1530 ELSE
1531
1532 --Left for backward compatibility.
1533
1534 v_result(1) := v_tExprPsNodeId(j);
1535 RETURN v_result;
1536 END IF;
1537
1538 v_index := glIndexByPsNodeId(v_ps_node_id);
1539 v_node_type := glPsNodeType(v_index);
1540 v_start_index := v_index + 1;
1541
1542 IF(NOT glLastChildIndex.EXISTS(v_ps_node_id))THEN
1543
1544 localString := glName(v_index);
1545 RAISE CZ_E_NO_EXPECTED_CHILDREN;
1546 END IF;
1547
1548 v_end_index := glLastChildIndex(v_ps_node_id);
1549 nCount := 1;
1550
1551 --If the function is called on a feature, we return options. If the function is called on a
1552 --BOM node, we return BOM children.
1553
1554 IF(v_node_type = PS_NODE_TYPE_FEATURE)THEN
1555
1556 FOR i IN v_start_index..v_end_index LOOP
1557
1558 v_result(nCount) := glPsNodeId(i);
1559 v_ExplByPsNodeId(glPsNodeId(i)) := v_tExplNodeId(j);
1560 nCount := nCount + 1;
1561 END LOOP;
1562 ELSIF(v_node_type IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
1563
1564 FOR i IN v_start_index..v_end_index LOOP
1565
1566 IF((glPsNodeType(i) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD) OR
1567 (glPsNodeType(i) = PS_NODE_TYPE_REFERENCE AND
1568 glPsNodeType(glIndexByPsNodeId(glReferenceId(glPsNodeId(i)))) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD)))
1569 AND glParentId(i) = v_ps_node_id)THEN
1570
1571 IF(glPsNodeType(i) = PS_NODE_TYPE_REFERENCE)THEN
1572 v_result(nCount) := glReferenceId(glPsNodeId(i));
1573 v_ExplByPsNodeId(glReferenceId(glPsNodeId(i))) := ADJUSTED_EXPLOSION(v_tExplNodeId(j), glPsNodeId(i));
1574 ELSE
1575 v_result(nCount) := glPsNodeId(i);
1576 v_ExplByPsNodeId(glPsNodeId(i)) := v_tExplNodeId(j);
1577 END IF;
1578 nCount := nCount + 1;
1579 END IF;
1580 END LOOP;
1581 END IF;
1582 RETURN v_result;
1583 END;
1584 ---------------------------------------------------------------------------------------
1585 FUNCTION GENERATE_CHILDRENOF(p_expl_id IN PLS_INTEGER, p_ps_node_id IN NUMBER) RETURN tStringArray IS --kdande; Bug 6881902; 11-Mar-2008
1586 v_return tStringArray;
1587 nCount PLS_INTEGER;
1588 v_node_type PLS_INTEGER;
1589 v_index PLS_INTEGER;
1590 v_start_index PLS_INTEGER;
1591 v_end_index PLS_INTEGER;
1592 BEGIN
1593
1594 nDebug := 7004050;
1595
1596 --This function does basically the same as the previous one. The difference is that it can be used
1597 --only for system property, it is called on the system property node, taking the ps_node_id of the
1598 --parent as a parameter, and it returns generated names.
1599
1600 v_index := glIndexByPsNodeId(p_ps_node_id);
1601 v_node_type := glPsNodeType(v_index);
1602 v_start_index := v_index + 1;
1603
1604 IF(NOT glLastChildIndex.EXISTS(p_ps_node_id))THEN
1605
1606 localString := glName(v_index);
1607 RAISE CZ_E_NO_EXPECTED_CHILDREN;
1608 END IF;
1609
1610 v_end_index := glLastChildIndex(p_ps_node_id);
1611 nCount := 1;
1612
1613 --If the function is called on a feature, we return options. If the function is called on a
1614 --BOM node, we return BOM children.
1615
1616 IF(v_node_type = PS_NODE_TYPE_FEATURE)THEN
1617
1618 FOR i IN v_start_index..v_end_index LOOP
1619
1620 v_return(nCount) := GENERATE_NAME_EXPL(p_expl_id, glPsNodeId(i));
1621 nCount := nCount + 1;
1622 END LOOP;
1623
1624 ELSIF(v_node_type IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
1625
1626 FOR i IN v_start_index..v_end_index LOOP
1627 IF((glPsNodeType(i) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD) OR
1628 (glPsNodeType(i) = PS_NODE_TYPE_REFERENCE AND
1629 glPsNodeType(glIndexByPsNodeId(glReferenceId(glPsNodeId(i)))) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD)))
1630 AND glParentId(i) = p_ps_node_id)THEN
1631
1632 IF(glPsNodeType(i) = PS_NODE_TYPE_REFERENCE)THEN
1633 v_return(nCount) := GENERATE_NAME_EXPL(ADJUSTED_EXPLOSION(p_expl_id, glPsNodeId(i)), glReferenceId(glPsNodeId(i)));
1634 ELSE
1635 v_return(nCount) := GENERATE_NAME_EXPL(p_expl_id, glPsNodeId(i));
1636 END IF;
1637 nCount := nCount + 1;
1638 END IF;
1639 END LOOP;
1640 END IF;
1641
1642 nDebug := 7004059;
1643
1644 RETURN v_return;
1645 END;
1646 ---------------------------------------------------------------------------------------
1647 FUNCTION GENERATE_ARITHMETIC(j IN PLS_INTEGER) RETURN tStringArray IS
1648
1649 v_return tStringArray;
1650 nChild PLS_INTEGER;
1651 nCount PLS_INTEGER;
1652 lhs tStringArray;
1653 rhs tStringArray;
1654 ListType PLS_INTEGER;
1655 v_rounding VARCHAR2(16) := ' ';
1656 v_target VARCHAR2(4000);
1657 v_parj PLS_INTEGER;
1658 optimizeFlag PLS_INTEGER := 0;
1659
1660 BEGIN
1661
1662 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
1663 RAISE CZ_E_WRONG_ARITHMETIC_OPER;
1664 END IF;
1665
1666 nCount := 1;
1667 nChild := v_ChildrenIndex(v_tExprId(j));
1668 IF(v_tExprParentId.EXISTS(nChild + 1) AND v_tExprParentId(nChild + 1) = v_tExprId(j))THEN
1669 nCount := 2;
1670 END IF;
1671
1672 nDebug := 8004002;
1673
1674 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
1675 nLocalDefaults := nLocalDefaults + 1;
1676 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
1677 v_target := 'TOTAL ' || v_return(1) || NewLine;
1678
1679 --Check if this procedure has been called for generation of a direct child expression of a rounding
1680 --operator. If so, set a flag to generate an enhanced contribute relation and no temporary total.
1681 --If the rounding operator is a root operator of a numeric rule with an advanced lhs expression,
1682 --which is indicated by the optimizeChain flag, generate the optimized contribute relation.
1683
1684 IF(v_tExprParentId(j) IS NOT NULL)THEN
1685
1686 v_parj := v_IndexByExprNodeId(v_tExprParentId(j));
1687
1688 IF(v_tExprType(v_parj) = EXPR_NODE_TYPE_OPERATOR AND
1689 v_tExprSubtype(v_parj) IN (OPERATOR_ROUND, OPERATOR_CEILING, OPERATOR_FLOOR, OPERATOR_TRUNCATE))THEN
1690
1691 v_rounding := OperatorLiterals(v_tExprSubtype(v_parj));
1692 generateRound := OPTIMIZATION_COMPLETED;
1693
1694 IF(optimizeChain = OPTIMIZATION_REQUESTED)THEN
1695
1696 v_return(1) := optimizeTarget;
1697 v_target := NULL;
1698 optimizeChain := OPTIMIZATION_COMPLETED;
1699 END IF;
1700 END IF;
1701 ELSIF(optimizeContribute = OPTIMIZATION_REQUESTED)THEN
1702
1703 optimizeFlag := 1;
1704 optimizeContribute := OPTIMIZATION_COMPLETED;
1705 END IF;
1706
1707 IF(nCount = 1)THEN
1708
1709 nDebug := 8004003;
1710
1711 lhs := GENERATE_EXPRESSION(nChild, ListType);
1712 IF(v_tExprSubtype(j) = OPERATOR_SUB)THEN
1713
1714 IF(optimizeFlag = 0)THEN
1715
1716 vLogicLine := v_target || 'CONTRIBUTE ' || lhs(1) || OperatorLiterals(OPERATOR_MULT) || '-1 ' ||
1717 v_return(1) || v_rounding || '... ' || TO_CHAR(nReasonId) || NewLine;
1718 ELSE
1719
1720 v_return(1) := lhs(1) || OperatorLiterals(OPERATOR_MULT) || '-1 ';
1721 END IF;
1722 ELSE
1723
1724 v_return(1) := lhs(1);
1725 END IF;
1726 ELSE
1727
1728 nDebug := 8004004;
1729
1730 lhs := GENERATE_EXPRESSION(nChild, ListType);
1731
1732 nDebug := 8004005;
1733
1734 rhs := GENERATE_EXPRESSION(nChild + 1, ListType);
1735
1736 nDebug := 8004006;
1737
1738 IF(optimizeFlag = 0)THEN
1739
1740 vLogicLine := v_target || 'CONTRIBUTE ' || lhs(1) || OperatorLiterals(v_tExprSubtype(j)) ||
1741 rhs(1) || ' ' || v_return(1) || v_rounding || '... ' || TO_CHAR(nReasonId) || NewLine;
1742 ELSE
1743
1744 v_return(1) := lhs(1) || OperatorLiterals(v_tExprSubtype(j)) || rhs(1) || ' ';
1745 END IF;
1746 END IF;
1747
1748 PACK;
1749 RETURN v_return;
1750 END;
1751 ---------------------------------------------------------------------------------------
1752 FUNCTION GENERATE_MATH_UNARY(j IN PLS_INTEGER) RETURN tStringArray IS
1753 v_return tStringArray;
1754 v_result tStringArray;
1755 nChild PLS_INTEGER;
1756 ListType PLS_INTEGER;
1757 BEGIN
1758
1759 nDebug := 7000100;
1760
1761 IF((NOT v_ChildrenIndex.EXISTS(v_tExprId(j))) OR v_NumberOfChildren(v_tExprId(j)) <> 1)THEN
1762 nParam := v_tExprSubtype(j);
1763 RAISE CZ_E_MATH_PARAMETERS;
1764 END IF;
1765
1766 nChild := v_ChildrenIndex(v_tExprId(j));
1767
1768 nDebug := 7000101;
1769
1770 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
1771 nLocalDefaults := nLocalDefaults + 1;
1772 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
1773
1774 nDebug := 7000102;
1775
1776 v_result := GENERATE_EXPRESSION(nChild, ListType);
1777
1778 nDebug := 7000103;
1779
1780 vLogicLine := 'TOTAL ' || v_return(1) || NewLine ||
1781 'MF ' || v_result(1) || OperatorLiterals(v_tExprSubtype(j)) ||
1782 v_return(1) || ' ... ' || TO_CHAR(nReasonId) || NewLine;
1783 PACK;
1784
1785 RETURN v_return;
1786 END;
1787 ---------------------------------------------------------------------------------------
1788 FUNCTION GENERATE_MATH_BINARY(j IN PLS_INTEGER) RETURN tStringArray IS
1789 v_return tStringArray;
1790 nChild PLS_INTEGER;
1791 lhs tStringArray;
1792 rhs tStringArray;
1793 ListType PLS_INTEGER;
1794 BEGIN
1795
1796 nDebug := 7000200;
1797
1798 IF((NOT v_ChildrenIndex.EXISTS(v_tExprId(j))) OR v_NumberOfChildren(v_tExprId(j)) <> 2)THEN
1799 nParam := v_tExprSubtype(j);
1800 RAISE CZ_E_MATH_PARAMETERS;
1801 END IF;
1802
1803 nChild := v_ChildrenIndex(v_tExprId(j));
1804
1805 nDebug := 7000201;
1806
1807 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
1808 nLocalDefaults := nLocalDefaults + 1;
1809 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
1810
1811 nDebug := 7000202;
1812
1813 lhs := GENERATE_EXPRESSION(nChild, ListType);
1814
1815 nDebug := 7000203;
1816
1817 rhs := GENERATE_EXPRESSION(nChild + 1, ListType);
1818
1819 --Bug #1990405. For the pow function, the second operand must evaluate to an integer. This
1820 --requirement may be removed or modified later.
1821
1822 IF(v_tExprSubtype(j) = OPERATOR_POW)THEN
1823
1824 --The generated expression should be an integer constant.
1825
1826 IF(REPLACE(TRANSLATE(rhs(1), '0123456789', '0000000000'), '0', NULL) IS NOT NULL)THEN
1827 RAISE CZ_E_INCORRECT_POWER;
1828 END IF;
1829 END IF;
1830
1831 nDebug := 7000204;
1832
1833 vLogicLine := 'TOTAL ' || v_return(1) || NewLine ||
1834 'MF ' || lhs(1) || ' ' || rhs(1) || OperatorLiterals(v_tExprSubtype(j)) ||
1835 v_return(1) || ' ... ' || TO_CHAR(nReasonId) || NewLine;
1836 PACK;
1837
1838 RETURN v_return;
1839 END;
1840 ---------------------------------------------------------------------------------------
1841 FUNCTION GENERATE_MATH_ROUND(j IN PLS_INTEGER) RETURN tStringArray IS
1842 v_return tStringArray;
1843 nChild PLS_INTEGER;
1844 lhs tStringArray;
1845 rhs tStringArray;
1846 ListType PLS_INTEGER;
1847 sReasonId VARCHAR2(4000) := TO_CHAR(nReasonId);
1848 BEGIN
1849
1850 nDebug := 7000300;
1851
1852 IF((NOT v_ChildrenIndex.EXISTS(v_tExprId(j))) OR v_NumberOfChildren(v_tExprId(j)) <> 2)THEN
1853 nParam := v_tExprSubtype(j);
1854 RAISE CZ_E_MATH_PARAMETERS;
1855 END IF;
1856
1857 nChild := v_ChildrenIndex(v_tExprId(j));
1858
1859 nDebug := 7000301;
1860
1861 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
1862 nLocalDefaults := nLocalDefaults + 1;
1863 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
1864
1865 nDebug := 7000302;
1866
1867 lhs := GENERATE_EXPRESSION(nChild, ListType);
1868
1869 nDebug := 7000303;
1870
1871 rhs := GENERATE_EXPRESSION(nChild + 1, ListType);
1872
1873 nDebug := 7000304;
1874
1875 vLogicLine := 'TOTAL ' || v_return(1) || '_1' || NewLine ||
1876 'MF ' || lhs(1) || ' ' || rhs(1) || OperatorLiterals(OPERATOR_MATHDIV) ||
1877 v_return(1) || '_1 ... ' || sReasonId || NewLine;
1878 PACK;
1879 vLogicLine := 'TOTAL ' || v_return(1) || '_2' || NewLine ||
1880 'MF ' || v_return(1) || '_1' || OperatorLiterals(v_tExprSubtype(j)) ||
1881 v_return(1) || '_2 ... ' || sReasonId || NewLine;
1882 PACK;
1883 vLogicLine := 'TOTAL ' || v_return(1) || NewLine ||
1884 'CONTRIBUTE ' || rhs(1) || OperatorLiterals(OPERATOR_MULT) ||
1885 v_return(1) || '_2 ' || v_return(1) || ' ... ' || sReasonId || NewLine;
1886 PACK;
1887
1888 RETURN v_return;
1889 END;
1890 ---------------------------------------------------------------------------------------
1891 FUNCTION GENERATE_LITERAL(j IN PLS_INTEGER) RETURN tStringArray IS
1892 v_return tStringArray;
1893 BEGIN
1894
1895 v_return(1) := v_tExprDataValue(j);
1896
1897 IF(v_tExprDataType(j) = DATA_TYPE_BOOLEAN)THEN
1898 IF(UPPER(v_tExprDataValue(j)) IN ('1', LOGICAL_CONSTANT_TRUE))THEN
1899
1900 v_return(1) := ALWAYS_TRUE;
1901 ELSIF(UPPER(v_tExprDataValue(j)) IN ('0', LOGICAL_CONSTANT_FALSE))THEN
1902
1903 v_return(1) := ALWAYS_FALSE;
1904 END IF;
1905
1906 --Bug #4375977.
1907
1908 IF(v_tLogicNetType(nHeaderId) = LOGIC_NET_TYPE_NETWORK AND (NOT v_IsConnectorNet.EXISTS(v_tExplNodeId(j))))THEN
1909
1910 --If we are generating into a conditional net, we add an extra ^parent to the path, but only if
1911 --this is not a connector's net.
1912
1913 v_return(1) := PATH_DELIMITER || 'parent' || PATH_DELIMITER || v_return(1);
1914 END IF;
1915 END IF;
1916 RETURN v_return;
1917 END;
1918 ---------------------------------------------------------------------------------------
1919 FUNCTION GENERATE_CONSTANT(j IN PLS_INTEGER) RETURN tStringArray IS
1920 v_return tStringArray;
1921 BEGIN
1922 IF(v_tExprSubtype(j) = EXPR_SUBTYPE_CONSTANT_E)THEN
1923
1924 IF(NOT h_HeaderEDefined.EXISTS(nHeaderId))THEN
1925 h_HeaderEDefined(nHeaderId) := 'T_' || TO_CHAR(nHeaderId) || '_E';
1926 vLogicLine := 'TOTAL ' || h_HeaderEDefined(nHeaderId) || ' ' || MATH_CONSTANT_E || NewLine;
1927 PACK;
1928 END IF;
1929 v_return(1) := h_HeaderEDefined(nHeaderId);
1930
1931 ELSIF(v_tExprSubtype(j) = EXPR_SUBTYPE_CONSTANT_PI)THEN
1932
1933 IF(NOT h_HeaderPiDefined.EXISTS(nHeaderId))THEN
1934 h_HeaderPiDefined(nHeaderId) := 'T_' || TO_CHAR(nHeaderId) || '_PI';
1935 vLogicLine := 'TOTAL ' || h_HeaderPiDefined(nHeaderId) || ' ' || MATH_CONSTANT_PI || NewLine;
1936 PACK;
1937 END IF;
1938 v_return(1) := h_HeaderPiDefined(nHeaderId);
1939
1940 ELSE
1941 RAISE CZ_E_UNKNOWN_EXPR_TYPE;
1942 END IF;
1943 RETURN v_return;
1944 END;
1945 ---------------------------------------------------------------------------------------
1946 FUNCTION GENERATE_MINMAX(j IN PLS_INTEGER) RETURN tStringArray IS
1947 v_return tStringArray;
1948 v_child tStringArray;
1949 v_current VARCHAR2(4000);
1950 v_oper VARCHAR2(10) := OperatorLiterals(v_tExprSubtype(j));
1951 v_rounding VARCHAR2(16) := ' ';
1952 v_actual VARCHAR2(16) := ' ';
1953 v_parj PLS_INTEGER;
1954 v_target VARCHAR2(4000);
1955 doOptimize PLS_INTEGER := 0;
1956 v_name VARCHAR2(128);
1957 BEGIN
1958
1959 nLocalDefaults := nLocalDefaults + 1;
1960 v_name := TO_CHAR(nLocalDefaults);
1961
1962 v_child := GENERATE_NODE_CHILDREN(j);
1963 v_return(1) := t_prefix || v_name || '_1';
1964 v_target := 'TOTAL ' || v_return(1) || NewLine;
1965
1966 IF(v_child.COUNT < 2)THEN
1967 RAISE CZ_E_WRONG_MINMAX_OPERATOR;
1968 END IF;
1969
1970 --Check if this procedure has been called for generation of a direct child expression of a rounding
1971 --operator. If so, set a flag to generate an enhanced contribute relation and no temporary total.
1972 --If the rounding operator is a root operator of a numeric rule with an advanced lhs expression,
1973 --which is indicated by the optimizeChain flag, generate the optimized contribute relation.
1974
1975 IF(v_tExprParentId(j) IS NOT NULL)THEN
1976
1977 v_parj := v_IndexByExprNodeId(v_tExprParentId(j));
1978
1979 IF(v_tExprType(v_parj) = EXPR_NODE_TYPE_OPERATOR AND
1980 v_tExprSubtype(v_parj) IN (OPERATOR_ROUND, OPERATOR_CEILING, OPERATOR_FLOOR, OPERATOR_TRUNCATE))THEN
1981
1982 v_rounding := OperatorLiterals(v_tExprSubtype(v_parj));
1983 generateRound := OPTIMIZATION_COMPLETED;
1984
1985 IF(optimizeChain = OPTIMIZATION_REQUESTED)THEN
1986
1987 optimizeChain := OPTIMIZATION_COMPLETED;
1988 doOptimize := 1;
1989 END IF;
1990 END IF;
1991 END IF;
1992
1993 --If the operator has just two operands, only one contribute relation will be generated, prepare
1994 --variables for this relation.
1995
1996 IF(v_child.COUNT = 2)THEN
1997
1998 v_actual := v_rounding;
1999 IF(doOptimize = 1)THEN
2000
2001 v_target := NULL;
2002 v_return(1) := optimizeTarget;
2003 END IF;
2004 END IF;
2005
2006 vLogicLine := v_target || 'CONTRIBUTE ' || v_child(1) || v_oper || v_child(2) || ' ' ||
2007 v_return(1) || v_actual || '... ' || TO_CHAR(nReasonId) || NewLine;
2008
2009 PACK;
2010
2011 v_current := v_return(1);
2012 v_actual := ' ';
2013
2014 FOR i IN 3..v_child.COUNT LOOP
2015
2016 v_return(1) := t_prefix || v_name || '_' || TO_CHAR(i-1);
2017 v_target := 'TOTAL ' || v_return(1) || NewLine;
2018
2019 --If the operator has more than two operands, two or more contribute relations will be
2020 --generated. We want to modify only the last of them, so prepare the variables before
2021 --generating the last one.
2022
2023 IF(i = v_child.COUNT)THEN
2024
2025 v_actual := v_rounding;
2026 IF(doOptimize = 1)THEN
2027
2028 v_target := NULL;
2029 v_return(1) := optimizeTarget;
2030 END IF;
2031 END IF;
2032
2033 vLogicLine := v_target || 'CONTRIBUTE ' || v_child(i) || v_oper || v_current || ' ' ||
2034 v_return(1) || v_actual || '... ' || TO_CHAR(nReasonId) || NewLine;
2035
2036 v_current := v_return(1);
2037 PACK;
2038
2039 END LOOP;
2040 RETURN v_return;
2041 END;
2042 ---------------------------------------------------------------------------------------
2043 FUNCTION GENERATE_OF(j IN PLS_INTEGER) RETURN tStringArray IS
2044 v_return tStringArray;
2045 v_result tIntegerArray;
2046 nChild PLS_INTEGER;
2047 BEGIN
2048
2049 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
2050 RAISE CZ_E_WRONG_OF_OPERATOR;
2051 END IF;
2052
2053 nChild := v_ChildrenIndex(v_tExprId(j));
2054 v_result := EXPAND_NODE(j);
2055
2056 FOR i IN 1..v_result.COUNT LOOP
2057
2058 v_return(i) := GENERATE_NAME_EXPL(v_ExplByPsNodeId(v_result(i)), v_result(i));
2059 END LOOP;
2060
2061 RETURN v_return;
2062 END;
2063 ---------------------------------------------------------------------------------------
2064 FUNCTION GENERATE_NOT(j IN PLS_INTEGER) RETURN tStringArray IS
2065 v_return tStringArray;
2066 nChild PLS_INTEGER;
2067 oper tStringArray;
2068 ListType PLS_INTEGER;
2069 BEGIN
2070
2071 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
2072 RAISE CZ_E_WRONG_NOT_OPERATOR;
2073 END IF;
2074
2075 nChild := v_ChildrenIndex(v_tExprId(j));
2076 IF(v_tExprParentId.EXISTS(nChild + 1) AND v_tExprParentId(nChild + 1) = v_tExprId(j))THEN
2077 RAISE CZ_E_WRONG_NOT_OPERATOR;
2078 END IF;
2079
2080 IF(NOT HAS_LOGICAL_VALUE(nChild))THEN
2081 nParam := j;
2082 RAISE CZ_E_INVALID_OPERAND_TYPE;
2083 END IF;
2084
2085 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
2086 nLocalDefaults := nLocalDefaults + 1;
2087 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
2088
2089 oper := GENERATE_EXPRESSION(nChild, ListType);
2090
2091 vLogicLine := 'OBJECT ' || v_return(1) || NewLine ||
2092 'GS N ... ' || TO_CHAR(nReasonId) || NewLine ||
2093 'GL' || OperatorLetters(OPERATOR_ANYOF) || oper(1) || NewLine ||
2094 'GR' || OperatorLetters(OPERATOR_ANYOF) || v_return(1) || NewLine;
2095 PACK;
2096
2097 RETURN v_return;
2098 END;
2099 ---------------------------------------------------------------------------------------
2100 FUNCTION GENERATE_NOTTRUE(j IN PLS_INTEGER) RETURN tStringArray IS
2101 v_return tStringArray;
2102 nChild PLS_INTEGER;
2103 oper tStringArray;
2104 ListType PLS_INTEGER;
2105 v_NodeId NUMBER; --kdande; Bug 6881902; 11-Mar-2008
2106 v_HeaderId NUMBER;
2107 v_nodename VARCHAR2(4000);
2108 v_accuname VARCHAR2(4000);
2109 iLocal PLS_INTEGER;
2110 BEGIN
2111
2112 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
2113 RAISE CZ_E_WRONG_NOTTRUE_OPERATOR;
2114 END IF;
2115
2116 nChild := v_ChildrenIndex(v_tExprId(j));
2117 IF(v_tExprParentId.EXISTS(nChild + 1) AND v_tExprParentId(nChild + 1) = v_tExprId(j))THEN
2118 RAISE CZ_E_WRONG_NOTTRUE_OPERATOR;
2119 END IF;
2120
2121 IF(NOT HAS_LOGICAL_VALUE(nChild))THEN
2122 nParam := j;
2123 RAISE CZ_E_INVALID_OPERAND_TYPE;
2124 END IF;
2125
2126 --OptimizeNotTrue is a db setting which is disabled by default.
2127
2128 IF(OptimizeNotTrue = 0 OR v_tExprType(nChild) <> EXPR_NODE_TYPE_NODE)THEN
2129
2130 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
2131 nLocalDefaults := nLocalDefaults + 1;
2132 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
2133
2134 oper := GENERATE_EXPRESSION(nChild, ListType);
2135
2136 vLogicLine := 'OBJECT ' || v_return(1) || NewLine ||
2137 'NOTTRUE ' || oper(1) || ' ' || v_return(1) || ' ... ' || TO_CHAR(nReasonId) || NewLine;
2138 PACK;
2139 ELSE
2140
2141 v_NodeId := v_tExprPsNodeId(nChild);
2142
2143 IF((NOT v_HeaderByNotTrueId.EXISTS(v_NodeId)) AND
2144 (glAccumulator(v_NodeId) IS NULL OR glAccumulator(v_NodeId) = FLAG_NO_ACCUMULATOR))THEN
2145
2146 --Need to generate a new NOTTRUE relation in the node's structure file
2147
2148 v_HeaderId := glHeaderByPsNodeId(v_NodeId);
2149 v_nodename := 'P_' || TO_CHAR(glPersistentId(v_NodeId));
2150 v_accuname := v_nodename || '_NT';
2151
2152 --Flush off the buffer because we are about to write to another file
2153
2154 IF(vLogicText IS NOT NULL)THEN
2155 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
2156 (nHeaderId, v_tSequenceNbr(nHeaderId), vLogicText);
2157 vLogicText := NULL;
2158 v_tSequenceNbr(nHeaderId) := v_tSequenceNbr(nHeaderId) + 1;
2159 END IF;
2160
2161 --Fix for the bug #2398832 - we may be re-using the accumulator, so we should not
2162 --assign to it effectivities and usages of a particular node.
2163 --Do not write the effectivity dates using the actual effective date interval of
2164 --the corresponding node.
2165
2166 --iLocal := glIndexByPsNodeId(v_NodeId);
2167 --CurrentEffFrom := glEffFrom(iLocal);
2168 --CurrentEffUntil := glEffUntil(iLocal);
2169 --CurrentUsageMask := glUsageMask(iLocal);
2170
2171 --Instead make the accumulator always effective and universal.
2172
2173 CurrentEffFrom := EpochBeginDate;
2174 CurrentEffUntil := EpochEndDate;
2175 CurrentUsageMask := AnyUsageMask;
2176
2177 IF((NOT h_EffFrom.EXISTS(v_HeaderId)) OR
2178 (h_EffFrom(v_HeaderId) <> CurrentEffFrom OR h_EffUntil(v_HeaderId) <> CurrentEffUntil OR
2179 h_EffUsageMask(v_HeaderId) <> CurrentUsageMask))THEN
2180
2181 h_EffFrom(v_HeaderId) := CurrentEffFrom;
2182 h_EffUntil(v_HeaderId) := CurrentEffUntil;
2183 h_EffUsageMask(v_HeaderId) := CurrentUsageMask;
2184
2185 vLogicText := LTRIM(CurrentUsageMask, '0');
2186 IF(vLogicText IS NOT NULL) THEN
2187 vLogicText := EffUsagePrefix || vLogicText;
2188 END IF;
2189
2190 IF(CurrentEffFrom = EpochBeginDate)THEN
2191 CurrentFromDate := NULL;
2192 ELSE
2193 CurrentFromDate := TO_CHAR(CurrentEffFrom, EffDateFormat);
2194 END IF;
2195
2196 IF(CurrentEffUntil = EpochEndDate)THEN
2197 CurrentUntilDate := NULL;
2198 ELSE
2199 CurrentUntilDate := TO_CHAR(CurrentEffUntil, EffDateFormat);
2200 END IF;
2201
2202 vLogicText := 'EFF ' || CurrentFromDate || ', ' || CurrentUntilDate || ', ' || vLogicText || NewLine;
2203 END IF;
2204
2205 vLogicText := vLogicText || 'OBJECT ' || v_accuname || NewLine ||
2206 'NOTTRUE ' || v_nodename || ' ' || v_accuname || ' ... ' || TO_CHAR(nReasonId) || NewLine;
2207
2208 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
2209 (v_HeaderId, vSeqNbrByHeader(v_HeaderId), vLogicText);
2210 vLogicText := NULL;
2211 vSeqNbrByHeader(v_HeaderId) := vSeqNbrByHeader(v_HeaderId) + 1;
2212
2213 v_HeaderByNotTrueId(v_NodeId) := v_HeaderId;
2214
2215 --Part of the fix for the bug #2857955. We will never be here if glAccumulator(v_NodeId) was
2216 --FLAG_ACCUMULATOR_NT because the accumulator would have already been created.
2217
2218 UPDATE cz_ps_nodes SET
2219 accumulator_flag = DECODE(glAccumulator(v_NodeId), FLAG_ACCUMULATOR_ACC, FLAG_ACCUMULATOR_BOTH, FLAG_ACCUMULATOR_NT)
2220 WHERE ps_node_id = v_NodeId;
2221
2222 END IF;
2223
2224 v_return(1) := GENERATE_NAME(nChild, v_NodeId) || '_NT';
2225 END IF;
2226
2227 RETURN v_return;
2228 END;
2229 ---------------------------------------------------------------------------------------
2230 FUNCTION COMPARE_VALUES(val1 IN VARCHAR2, val2 IN VARCHAR2, OperType IN PLS_INTEGER)
2231 RETURN BOOLEAN IS
2232 v_null NUMBER;
2233 BEGIN
2234 IF(OperType = OPERATOR_EQUALS)THEN
2235 RETURN (val1 = val2);
2236 ELSIF(OperType = OPERATOR_NOTEQUALS)THEN
2237 RETURN (val1 <> val2);
2238 ELSIF(OperType = OPERATOR_EQUALS_INT)THEN
2239 RETURN (val1 = val2);
2240 ELSIF(OperType = OPERATOR_NOTEQUALS_INT)THEN
2241 RETURN (val1 <> val2);
2242 ELSIF(OperType = OPERATOR_GT)THEN
2243 RETURN (val1 > val2);
2244 ELSIF(OperType = OPERATOR_LT)THEN
2245 RETURN (val1 < val2);
2246 ELSIF(OperType = OPERATOR_GE)THEN
2247 RETURN (val1 >= val2);
2248 ELSIF(OperType = OPERATOR_LE)THEN
2249 RETURN (val1 <= val2);
2250 ELSIF(OperType = OPERATOR_BEGINSWITH)THEN
2251 RETURN (INSTR(val1, val2) = 1);
2252 ELSIF(OperType = OPERATOR_ENDSWITH)THEN
2253 RETURN (INSTR(val1, val2, -1) = (LENGTH(val1) - LENGTH(val2) + 1));
2254 ELSIF(OperType = OPERATOR_CONTAINS)THEN
2255 RETURN (INSTR(val1, val2) <> 0);
2256 ELSIF(OperType = OPERATOR_LIKE)THEN
2257 BEGIN
2258 SELECT NULL INTO v_null FROM DUAL WHERE val1 LIKE val2;
2259 RETURN TRUE;
2260 EXCEPTION
2261 WHEN NO_DATA_FOUND THEN
2262 RETURN FALSE;
2263 END;
2264 ELSIF(OperType = OPERATOR_MATCHES)THEN
2265 BEGIN
2266 SELECT NULL INTO v_null FROM DUAL WHERE val1 LIKE val2;
2267 RETURN TRUE;
2268 EXCEPTION
2269 WHEN NO_DATA_FOUND THEN
2270 RETURN FALSE;
2271 END;
2272 ELSIF(OperType = OPERATOR_DOESNOTBEGINWITH)THEN
2273 RETURN (INSTR(val1, val2) <> 1);
2274 ELSIF(OperType = OPERATOR_DOESNOTENDWITH)THEN
2275 RETURN (INSTR(val1, val2, -1) <> (LENGTH(val1) - LENGTH(val2) + 1));
2276 ELSIF(OperType = OPERATOR_DOESNOTCONTAIN)THEN
2277 RETURN (INSTR(val1, val2) = 0);
2278 ELSIF(OperType = OPERATOR_NOTLIKE)THEN
2279 BEGIN
2280 SELECT NULL INTO v_null FROM DUAL WHERE val1 NOT LIKE val2;
2281 RETURN TRUE;
2282 EXCEPTION
2283 WHEN NO_DATA_FOUND THEN
2284 RETURN FALSE;
2285 END;
2286 ELSE
2287 RAISE CZ_E_WRONG_COMPARISON_OPER;
2288 END IF;
2289 END;
2290 ---------------------------------------------------------------------------------------
2291 FUNCTION EXTRACT_PROPERTY_VALUE(inVal IN VARCHAR2, inType IN PLS_INTEGER)
2292 RETURN VARCHAR2 IS
2293 BEGIN
2294 IF(inType = DATATYPE_STRING)THEN
2295 RETURN SUBSTR(inVal, INSTR(inVal, PROPERTY_DELIMITER) + 1);
2296 ELSE
2297 RETURN inVal;
2298 END IF;
2299 END;
2300 ---------------------------------------------------------------------------------------
2301 FUNCTION EXTRACT_PROPERTY_VALUE(inVal IN VARCHAR2)
2302
2303 --This simplified version is used in GENERATE_REFNODE to extract boolean property values
2304 --represented as character '0'/'1' in the database.
2305
2306 RETURN VARCHAR2 IS
2307 BEGIN
2308 RETURN SUBSTR(inVal, INSTR(inVal, PROPERTY_DELIMITER) + 1);
2309 END;
2310 ---------------------------------------------------------------------------------------
2311 FUNCTION EXTRACT_PROPERTY_NODE(inVal IN VARCHAR2) RETURN VARCHAR2 IS
2312 BEGIN
2313 RETURN SUBSTR(inVal, 1, INSTR(inVal, PROPERTY_DELIMITER) - 1);
2314 END;
2315 ---------------------------------------------------------------------------------------
2316 FUNCTION GENERATE_CONCAT(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
2317 v_return tStringArray;
2318 nChild PLS_INTEGER;
2319 lhs tStringArray;
2320 rhs tStringArray;
2321 lListType PLS_INTEGER;
2322 rListType PLS_INTEGER;
2323 ExprId NUMBER := v_tExprId(j); --Bug13566997
2324 BEGIN
2325
2326 IF(NOT v_ChildrenIndex.EXISTS(ExprId))THEN
2327 RAISE CZ_E_WRONG_COMPARISON_OPER;
2328 END IF;
2329
2330 nChild := v_ChildrenIndex(ExprId);
2331 IF(NOT v_tExprParentId.EXISTS(nChild + 1) OR v_tExprParentId(nChild + 1) IS NULL OR
2332 v_tExprParentId(nChild + 1) <> ExprId)THEN
2333 RAISE CZ_E_WRONG_COMPARISON_OPER;
2334 END IF;
2335
2336 lhs := GENERATE_EXPRESSION(nChild, lListType);
2337 rhs := GENERATE_EXPRESSION(nChild+1, rListType);
2338
2339 v_return(1) := EXTRACT_PROPERTY_VALUE(lhs(1)) || EXTRACT_PROPERTY_VALUE(rhs(1));
2340 ListType := DATA_TYPE_TEXT;
2341 RETURN v_return;
2342 END;
2343 ---------------------------------------------------------------------------------------
2344 --Bug 5620750 - function to generate the new ToText operator when used outside of PBC
2345 --context.
2346
2347 FUNCTION GENERATE_TOTEXT(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
2348 v_return tStringArray;
2349 ExprId NUMBER := v_tExprId(j); --Bug13566997
2350 BEGIN
2351
2352 IF((NOT v_ChildrenIndex.EXISTS(ExprId)) OR v_NumberOfChildren(ExprId) <> 1)THEN
2353 RAISE CZ_R_WRONG_EXPRESSION_NODE;
2354 END IF;
2355
2356 v_return(1) := TO_CHAR(v_tExprDataNumValue(v_ChildrenIndex(ExprId)));
2357 ListType := DATA_TYPE_TEXT;
2358 RETURN v_return;
2359 END;
2360 ---------------------------------------------------------------------------------------
2361 FUNCTION GENERATE_COMPARE(j IN PLS_INTEGER) RETURN tStringArray IS
2362 v_return tStringArray;
2363 v_left tStringArray;
2364 nChild PLS_INTEGER;
2365 lhs tStringArray;
2366 rhs tStringArray;
2367 lListType PLS_INTEGER;
2368 rListType PLS_INTEGER;
2369 OperType PLS_INTEGER := v_tExprSubtype(j);
2370 ExprId NUMBER := v_tExprId(j); --Bug13566997
2371 nCount PLS_INTEGER := 1;
2372 BEGIN
2373
2374 IF(NOT v_ChildrenIndex.EXISTS(ExprId))THEN
2375 RAISE CZ_E_WRONG_COMPARISON_OPER;
2376 END IF;
2377
2378 nChild := v_ChildrenIndex(ExprId);
2379 IF(NOT v_tExprParentId.EXISTS(nChild + 1) OR v_tExprParentId(nChild + 1) IS NULL OR
2380 v_tExprParentId(nChild + 1) <> ExprId)THEN
2381 RAISE CZ_E_WRONG_COMPARISON_OPER;
2382 END IF;
2383
2384 nDebug := 8001120;
2385
2386 --v_return(1) := 'T_' || TO_CHAR(ExprId);
2387 nLocalDefaults := nLocalDefaults + 1;
2388 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
2389
2390 nDebug := 8001121;
2391
2392 generateCompare := 1;
2393 lhs := GENERATE_EXPRESSION(nChild, lListType);
2394
2395 nDebug := 8001122;
2396
2397 rhs := GENERATE_EXPRESSION(nChild+1, rListType);
2398 generateCompare := 0;
2399
2400 --Bug #4191838.
2401
2402 IF(lhs.COUNT = 1 AND lListType = DATA_TYPE_TEXT AND rhs.COUNT = 1 AND rListType = DATA_TYPE_TEXT)THEN
2403
2404 v_left(1) := 'OBJECT ' || v_return(1) || NewLine;
2405 v_left(2) := TO_CHAR(nReasonId) || NewLine ||
2406 'GL' || OperatorLetters(OPERATOR_ALLOF) || ALWAYS_TRUE || NewLine ||
2407 'GR' || OperatorLetters(OPERATOR_ALLOF) || v_return(1) || NewLine;
2408
2409 IF(COMPARE_VALUES(EXTRACT_PROPERTY_VALUE(lhs(1), lListType),
2410 EXTRACT_PROPERTY_VALUE(rhs(1), rListType), OperType))THEN
2411 vLogicLine := v_left(1) || 'GS R ... ' || v_left(2);
2412 ELSE
2413 vLogicLine := v_left(1) || 'GS E ... ' || v_left(2);
2414 END IF;
2415 PACK;
2416 RETURN v_return;
2417 END IF;
2418
2419 nDebug := 8001123;
2420
2421 IF(lListType = DATATYPE_STRING OR rListType = DATATYPE_STRING)THEN
2422
2423 nDebug := 8001124;
2424
2425 FOR ii IN 1..lhs.COUNT LOOP
2426 FOR jj IN 1..rhs.COUNT LOOP
2427
2428 IF(COMPARE_VALUES(EXTRACT_PROPERTY_VALUE(lhs(ii), lListType),
2429 EXTRACT_PROPERTY_VALUE(rhs(jj), rListType), OperType))THEN
2430 IF(lListType = DATATYPE_STRING AND rListType = DATATYPE_STRING)THEN
2431
2432 nDebug := 8001125;
2433
2434 v_left(nCount) := v_return(1) || '_' || TO_CHAR(nCount);
2435
2436 vLogicLine := 'OBJECT ' || v_left(nCount) || NewLine ||
2437 'GS R ' || sUnsatisfiedId || '... ' || TO_CHAR(nReasonId) || NewLine ||
2438 'GL' || OperatorLetters(OPERATOR_ALLOF) ||
2439 EXTRACT_PROPERTY_NODE(lhs(ii)) || ' ' || EXTRACT_PROPERTY_NODE(rhs(jj)) || NewLine ||
2440 'GR' || OperatorLetters(OPERATOR_ALLOF) || v_left(nCount) || NewLine;
2441 PACK;
2442 nCount := nCount + 1;
2443
2444 ELSIF(lListType = DATATYPE_STRING)THEN
2445
2446 nDebug := 8001126;
2447
2448 v_left(nCount) := EXTRACT_PROPERTY_NODE(lhs(ii));
2449 nCount := nCount + 1;
2450
2451 ELSIF(rListType = DATATYPE_STRING)THEN
2452
2453 nDebug := 8001127;
2454
2455 v_left(nCount) := EXTRACT_PROPERTY_NODE(rhs(jj));
2456 nCount := nCount + 1;
2457
2458 END IF;
2459 END IF;
2460 END LOOP;
2461 END LOOP;
2462
2463 nDebug := 8001128;
2464
2465 IF(v_left.COUNT = 0)THEN
2466
2467 vLogicLine := 'OBJECT ' || v_return(1) || NewLine ||
2468 'GS E ...' || TO_CHAR(nReasonId) || NewLine ||
2469 'GL' || OperatorLetters(OPERATOR_ALLOF) || ALWAYS_TRUE || NewLine ||
2470 'GR' || OperatorLetters(OPERATOR_ALLOF) || v_return(1) || NewLine;
2471
2472 ELSE
2473
2474 localString := NULL;
2475 IF(v_left.COUNT > 1)THEN localString := sUnsatisfiedId; END IF;
2476
2477 vLogicLine := 'OBJECT ' || v_return(1) || NewLine ||
2478 'GS R ' || localString || '... ' || TO_CHAR(nReasonId) || NewLine ||
2479 'GL' || OperatorLetters(OPERATOR_ANYOF);
2480
2481 PACK;
2482
2483 nDebug := 8001129;
2484
2485 FOR i IN 1..v_left.COUNT LOOP
2486
2487 vLogicLine := v_left(i) || ' ';
2488 PACK;
2489
2490 END LOOP;
2491
2492 vLogicLine := NewLine || 'GR' || OperatorLetters(OPERATOR_ALLOF) || v_return(1) || NewLine;
2493
2494 nDebug := 8001130;
2495
2496 END IF;
2497
2498 ELSE
2499
2500 nDebug := 8001131;
2501
2502 vLogicLine := 'OBJECT ' || v_return(1) || NewLine ||
2503 'COMPARE ' || lhs(1) || OperatorLiterals(OperType) ||
2504 rhs(1) || ' ' || v_return(1) || ' ... ' || TO_CHAR(nReasonId) || NewLine;
2505 END IF;
2506
2507 PACK;
2508
2509 RETURN v_return;
2510 END;
2511 ---------------------------------------------------------------------------------------
2512 FUNCTION GENERATE_ANYALLOF(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
2513 v_return tStringArray;
2514 v_child tStringArray;
2515 v_parentid NUMBER;
2516 v_parj PLS_INTEGER;
2517 nChild PLS_INTEGER;
2518 BEGIN
2519
2520 --nDebug := 7000001;
2521
2522 --Bug #5015333 - need a verification for the logical nature of the operands.
2523
2524 nChild := v_ChildrenIndex(v_tExprId(j));
2525
2526 WHILE(v_tExprParentId(nChild) = v_tExprId(j)) LOOP
2527
2528 IF(NOT HAS_LOGICAL_VALUE(nChild))THEN
2529
2530 nParam := j;
2531 RAISE CZ_E_INVALID_OPERAND_TYPE;
2532 END IF;
2533
2534 nChild := nChild + 1;
2535 END LOOP;
2536
2537 v_child := GENERATE_NODE_CHILDREN(j);
2538 v_parentid := v_tExprParentId(j);
2539
2540 --This is important that this assignment goes after the node children generation, because the
2541 --type of the parent operator can be changed during the children generation in some cases
2542 --(see internal case #3 below).
2543
2544 ListType := v_tExprSubtype(j);
2545
2546 IF(OptimizeAllAnyOf = 1)THEN
2547 IF(v_parentid IS NOT NULL)THEN
2548
2549 v_parj := v_IndexByExprNodeId(v_parentid);
2550
2551 IF(v_tExprType(v_parj) = EXPR_NODE_TYPE_OPERATOR AND
2552 v_tExprSubtype(v_parj) IN (OPERATOR_ANYOF, OPERATOR_ALLOF))THEN
2553
2554 IF(ListType = v_tExprSubtype(v_parj))THEN
2555
2556 --AllOf(AllOf(...) , ...), AnyOf(AnyOf(...) , ...).
2557 --Internal case #1.
2558
2559 return v_child;
2560 ELSIF(v_child.COUNT = 1)THEN
2561
2562 --This operator is either AnyOf or AllOf. It is different from the parent operator which
2563 --is also AnyOf or AllOf. Therefore, this is AllOf(AnyOf(...) , ...) or
2564 --AnyOf(AllOf(...) , ...). If only one child has been generated for this operator than
2565 --we have the case of AllOf(AnyOf(1) , ...) or AnyOf(AllOf(1) , ...).
2566 --Internal case #2.
2567
2568 return v_child;
2569
2570 ELSIF(v_NumberOfChildren(v_parentid) = 1)THEN
2571
2572 --We have AllOf(AnyOf(...)) or AnyOf(AllOf(...)), i. e. this AllOf or AnyOf operator is
2573 --the only child of its parent.If so, we not only carry over the children list but also
2574 --reverse the type of the parent operator.
2575 --Internal case #3.
2576
2577 v_tExprSubtype(v_parj) := ListType;
2578 return v_child;
2579 END IF;
2580 END IF;
2581 ELSIF(nRuleType = RULE_TYPE_LOGIC_RULE)THEN
2582 IF(nRuleOperator <> RULE_OPERATOR_DEFAULTS OR j = jConsequentRoot)THEN
2583 return v_child;
2584 ELSIF(v_child.COUNT = 1)THEN
2585 return v_child;
2586 END IF;
2587 END IF;
2588 END IF;
2589
2590 --nDebug := 7000002;
2591
2592 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
2593 nLocalDefaults := nLocalDefaults + 1;
2594 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
2595
2596 --nDebug := 7000003;
2597
2598 localString := NULL;
2599 IF(v_child.COUNT > 1)THEN localString := sUnsatisfiedId; END IF;
2600
2601 vLogicLine := 'OBJECT ' || v_return(1) || NewLine ||
2602 'GS R ' || localString || '... ' || TO_CHAR(nReasonId) || NewLine ||
2603 'GL' || OperatorLetters(ListType);
2604
2605 PACK;
2606
2607 IF(ChangeChildrenOrder = 1)THEN
2608 FOR i IN REVERSE 1..v_child.COUNT LOOP
2609
2610 vLogicLine := v_child(i) || ' ';
2611 PACK;
2612
2613 END LOOP;
2614 ELSE
2615 FOR i IN 1..v_child.COUNT LOOP
2616
2617 vLogicLine := v_child(i) || ' ';
2618 PACK;
2619
2620 END LOOP;
2621 END IF;
2622
2623 --nDebug := 7000004;
2624
2625 vLogicLine := NewLine || 'GR' || OperatorLetters(OPERATOR_ALLOF) || v_return(1) || NewLine;
2626 PACK;
2627 RETURN v_return;
2628 END;
2629 ---------------------------------------------------------------------------------------
2630 FUNCTION GENERATE_ANDOR(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
2631 v_return tStringArray;
2632 nChild PLS_INTEGER;
2633 lhs tStringArray;
2634 rhs tStringArray;
2635 lListType PLS_INTEGER;
2636 rListType PLS_INTEGER;
2637 BEGIN
2638
2639 IF((NOT v_ChildrenIndex.EXISTS(v_tExprId(j))) OR v_NumberOfChildren(v_tExprId(j)) <> 2)THEN
2640 RAISE CZ_E_WRONG_ANDOR_OPERATOR;
2641 END IF;
2642
2643 nChild := v_ChildrenIndex(v_tExprId(j));
2644
2645 IF(NOT (HAS_LOGICAL_VALUE(nChild) AND HAS_LOGICAL_VALUE(nChild + 1)))THEN
2646 nParam := j;
2647 RAISE CZ_E_INVALID_OPERAND_TYPE;
2648 END IF;
2649
2650 IF(OptimizeAllAnyOf = 1)THEN
2651 IF(v_tExprSubtype(j) = OPERATOR_AND)THEN
2652 v_tExprSubtype(j) := OPERATOR_ALLOF;
2653 ELSE
2654 v_tExprSubtype(j) := OPERATOR_ANYOF;
2655 END IF;
2656 RETURN GENERATE_ANYALLOF(j, ListType);
2657 END IF;
2658
2659 nDebug := 8001700;
2660
2661 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
2662 nLocalDefaults := nLocalDefaults + 1;
2663 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
2664
2665 lhs := GENERATE_EXPRESSION(nChild, lListType);
2666 rhs := GENERATE_EXPRESSION(nChild+1, rListType);
2667
2668 nDebug := 8001701;
2669
2670 vLogicLine := 'OBJECT ' || v_return(1) || NewLine ||
2671 'GS R ' || sUnsatisfiedId || '... ' || TO_CHAR(nReasonId) || NewLine ||
2672 'GL' || OperatorLetters(v_tExprSubtype(j)) || lhs(1) || ' ' || rhs(1) || NewLine ||
2673 'GR' || OperatorLetters(OPERATOR_ANYOF) || v_return(1) || NewLine;
2674 PACK;
2675
2676 nDebug := 8001702;
2677
2678 RETURN v_return;
2679 END;
2680 ---------------------------------------------------------------------------------------
2681 FUNCTION GENERATE_ROUND(j IN PLS_INTEGER) RETURN tStringArray IS
2682 v_return tStringArray;
2683 nChild PLS_INTEGER;
2684 oper tStringArray;
2685 ListType PLS_INTEGER;
2686 BEGIN
2687
2688 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
2689 RAISE CZ_E_WRONG_ROUND_OPERATOR;
2690 END IF;
2691
2692 nChild := v_ChildrenIndex(v_tExprId(j));
2693 IF(v_tExprParentId.EXISTS(nChild + 1) AND v_tExprParentId(nChild + 1)= v_tExprId(j))THEN
2694
2695 RAISE CZ_E_WRONG_ROUND_OPERATOR;
2696 END IF;
2697
2698 generateRound := OPTIMIZATION_REQUESTED;
2699
2700 oper := GENERATE_EXPRESSION(nChild, ListType);
2701
2702 --The value may have been changed by the child expression generation. In this case we are
2703 --optimizing and do not want the increment relation to be generated at all.
2704
2705 IF(generateRound = OPTIMIZATION_REQUESTED)THEN
2706
2707 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
2708 nLocalDefaults := nLocalDefaults + 1;
2709 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
2710
2711 vLogicLine := 'TOTAL ' || v_return(1) || NewLine || 'INC ' || oper(1) || ' ' || v_return(1) ||
2712 OperatorLiterals(v_tExprSubtype(j)) || '... ' || TO_CHAR(nReasonId) || NewLine;
2713 PACK;
2714 generateRound := OPTIMIZATION_COMPLETED;
2715 ELSE
2716
2717 v_return(1) := oper(1);
2718 END IF;
2719
2720 RETURN v_return;
2721 END;
2722 ---------------------------------------------------------------------------------------
2723 FUNCTION PROPERTY_VALUE(j IN PLS_INTEGER, iPSN IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER)
2724 RETURN VARCHAR2 IS
2725 v_return VARCHAR2(4000);
2726 nChild NUMBER;
2727 c_values refCursor;
2728 optionId cz_ps_nodes.ps_node_id%TYPE := glPsNodeId(iPSN);
2729 propertyId cz_expression_nodes.property_id%TYPE := v_tExprPropertyId(j);
2730 itemId cz_ps_nodes.item_id%TYPE := glItemId(iPSN);
2731 sysPropName VARCHAR2(30);
2732 BEGIN
2733
2734 IF(v_tExprType(j) = EXPR_SYS_PROP)THEN
2735
2736 IF(NOT h_SeededName.EXISTS(v_tExprSubtype(j)))THEN RAISE CZ_E_BAD_PROPERTY_TYPE; END IF;
2737 sysPropName := h_SeededName(v_tExprSubtype(j));
2738
2739 IF(sysPropName = RULE_SYS_PROP_NAME)THEN
2740
2741 --nDebug := 8001160;
2742
2743 v_return := glName(iPSN);
2744 ListType := DATATYPE_STRING;
2745
2746 ELSIF(sysPropName = RULE_SYS_PROP_QUANTITY)THEN
2747
2748 --Related bug: #2317427.
2749
2750 v_return := GENERATE_NAME(j, optionId);
2751 ListType := DATATYPE_INTEGER;
2752
2753 ELSIF(sysPropName = RULE_SYS_PROP_INSTANCECOUNT)THEN
2754
2755 --nDebug := 8001161;
2756
2757 --If it is a non-virtual component/product/reference, we add _ACTUALCOUNT to the name.
2758 --If it is a virtual component/product/reference, we return '1'.
2759 --If it is an option, we just generate the name.
2760
2761 IF(glPsNodeType(iPSN) IN (PS_NODE_TYPE_COMPONENT,
2762 PS_NODE_TYPE_REFERENCE,
2763 PS_NODE_TYPE_PRODUCT))THEN
2764 IF(glVirtualFlag(iPSN) = FLAG_NON_VIRTUAL)THEN
2765 v_return := GENERATE_NAME(j, optionId)||'_ACTUALCOUNT';
2766 ELSE
2767 v_return := '1';
2768 END IF;
2769 ELSE
2770 v_return := GENERATE_NAME(j, optionId);
2771 END IF;
2772 ListType := DATATYPE_INTEGER;
2773
2774 --nDebug := 8001162;
2775
2776 ELSIF(sysPropName = RULE_SYS_PROP_MININSTANCE)THEN
2777
2778 --nDebug := 8001163;
2779
2780 v_return := GENERATE_NAME(j, optionId)||'_MIN';
2781 ListType := DATATYPE_INTEGER;
2782
2783 ELSIF(sysPropName = RULE_SYS_PROP_MAXINSTANCE)THEN
2784
2785 --nDebug := 8001164;
2786
2787 v_return := GENERATE_NAME(j, optionId)||'_MAX';
2788 ListType := DATATYPE_INTEGER;
2789
2790 ELSE
2791
2792 RAISE CZ_E_BAD_PROPERTY_TYPE;
2793 END IF;
2794 ELSE
2795
2796 BEGIN
2797
2798 --nDebug := 8001165;
2799
2800 v_return := GET_PROPERTY_VALUE(optionId, propertyId, itemId, ListType);
2801
2802 IF(v_return IS NULL)THEN RAISE CZ_E_NULL_PROPERTY_VALUE; END IF;
2803
2804 IF(ListType IN (DATATYPE_INTEGER, DATATYPE_FLOAT))THEN
2805
2806 BEGIN
2807 nChild := TO_NUMBER(v_return);
2808 EXCEPTION
2809 WHEN OTHERS THEN
2810
2811 SELECT name INTO errorMessage
2812 FROM cz_properties
2813 WHERE property_id = propertyId;
2814
2815 localString := v_return;
2816 RAISE CZ_R_INCORRECT_DATA_TYPE;
2817 END;
2818 END IF;
2819
2820 EXCEPTION
2821 WHEN NO_DATA_FOUND THEN
2822 RAISE CZ_E_NO_SUCH_PROPERTY;
2823 WHEN TOO_MANY_ROWS THEN
2824 RAISE CZ_E_INCORRECT_PROPERTY;
2825 WHEN OTHERS THEN
2826 RAISE;
2827 END;
2828 END IF;
2829
2830 RETURN v_return;
2831 END;
2832 ---------------------------------------------------------------------------------------
2833 FUNCTION STATIC_SYSPROP_VALUE(p_node_id IN NUMBER, p_rule_id IN NUMBER, p_parent_up IN PLS_INTEGER)
2834 RETURN VARCHAR2 IS
2835
2836 optionIndex PLS_INTEGER;
2837 v_step PLS_INTEGER := p_parent_up;
2838 sysPropName cz_rules.name%TYPE;
2839 v_return VARCHAR2(4000);
2840 BEGIN
2841
2842 sysPropName := h_SeededName(p_rule_id);
2843 errorMessage := h_ReportName(p_rule_id);
2844 optionIndex := glIndexByPsNodeId(p_node_id);
2845
2846 BEGIN
2847 WHILE(v_step > 1)LOOP
2848 optionIndex := glIndexByPsNodeId(glParentId(optionIndex));
2849 v_step := v_step - 1;
2850 END LOOP;
2851 EXCEPTION
2852 WHEN OTHERS THEN
2853 RAISE CZ_E_INCORRECT_PROPERTY;
2854 END;
2855
2856 IF(sysPropName = RULE_SYS_PROP_NAME)THEN
2857
2858 v_return := glName(optionIndex);
2859
2860 ELSIF(sysPropName IN (RULE_SYS_PROP_MINVALUE, RULE_SYS_PROP_MINQUANTITY, RULE_SYS_PROP_MINSELECTED))THEN
2861
2862 v_return := glMinimum(optionIndex);
2863
2864 ELSIF(sysPropName IN (RULE_SYS_PROP_MAXVALUE, RULE_SYS_PROP_MAXQUANTITY, RULE_SYS_PROP_MAXSELECTED))THEN
2865
2866 v_return := glMaximum(optionIndex);
2867
2868 ELSIF(sysPropName = RULE_SYS_PROP_DESCRIPTION)THEN
2869
2870 RAISE CZ_E_DESCRIPTION_IN_WHERE;
2871 ELSE
2872
2873 RAISE CZ_E_PROPERTY_NOT_STATIC;
2874 END IF;
2875
2876 RETURN v_return;
2877 END;
2878 ---------------------------------------------------------------------------------------
2879 FUNCTION SYSTEM_PROPERTY_VALUE(j IN PLS_INTEGER, iPSN IN tStringArray, ListType OUT NOCOPY PLS_INTEGER)
2880 RETURN tStringArray IS
2881
2882 v_return tStringArray;
2883 v_result tStringArray;
2884 optionId cz_ps_nodes.ps_node_id%TYPE;
2885 propertyId cz_expression_nodes.property_id%TYPE := v_tExprPropertyId(j);
2886 itemId cz_ps_nodes.item_id%TYPE;
2887 c_values refCursor;
2888 nChild NUMBER;
2889 optionIndex PLS_INTEGER;
2890 sysPropName VARCHAR2(30);
2891 BEGIN
2892
2893 nDebug := 9001000;
2894
2895 FOR i IN 1..iPSN.COUNT LOOP
2896
2897 optionId := TO_NUMBER(iPSN(i));
2898 optionIndex := glIndexByPsNodeId(optionId);
2899
2900 IF(v_tExprType(j) = EXPR_NODE_TYPE_SYSPROP)THEN
2901
2902 sysPropName := h_SeededName(v_tExprSubtype(j));
2903
2904 IF(sysPropName = RULE_SYS_PROP_NAME)THEN
2905
2906 v_return(i) := glName(optionIndex);
2907 ListType := DATA_TYPE_TEXT;
2908
2909 ELSIF(sysPropName = RULE_SYS_PROP_DESCRIPTION)THEN
2910
2911 v_return(i) := glName(optionIndex);
2912 ListType := DATA_TYPE_TEXT;
2913
2914 ELSIF(sysPropName = RULE_SYS_PROP_PARENT)THEN
2915
2916 v_return(i) := TO_CHAR(glParentId(optionIndex));
2917 ListType := DATA_TYPE_NODE;
2918
2919 ELSIF(sysPropName = RULE_SYS_PROP_OPTIONS)THEN
2920
2921 v_result.DELETE;
2922 v_result := GENERATE_CHILDRENOF(v_tExplNodeId(j), TO_NUMBER(iPSN(i)));
2923
2924 FOR ii IN 1..v_result.COUNT LOOP
2925 v_return(v_return.COUNT + 1) := v_result(ii);
2926 END LOOP;
2927 ListType := DATA_TYPE_NODE_COLL;
2928
2929 ELSIF(sysPropName = RULE_SYS_PROP_MINVALUE)THEN
2930
2931 v_return(i) := GENERATE_NAME(j, optionId)||'_MIN';
2932 ListType := DATA_TYPE_INTEGER;
2933
2934 ELSIF(sysPropName = RULE_SYS_PROP_MAXVALUE)THEN
2935
2936 v_return(i) := GENERATE_NAME(j, optionId)||'_MAX';
2937 ListType := DATA_TYPE_INTEGER;
2938
2939 ELSIF(sysPropName = RULE_SYS_PROP_MINQUANTITY)THEN
2940
2941 v_return(i) := TO_CHAR(glMinimum(optionIndex));
2942 ListType := DATA_TYPE_INTEGER;
2943
2944 ELSIF(sysPropName = RULE_SYS_PROP_MAXQUANTITY)THEN
2945
2946 v_return(i) := TO_CHAR(glMaximum(optionIndex));
2947 ListType := DATA_TYPE_INTEGER;
2948
2949 ELSIF(sysPropName = RULE_SYS_PROP_MINSELECTED)THEN
2950
2951 v_return(i) := TO_CHAR(glMinimumSel(optionIndex));
2952 ListType := DATA_TYPE_INTEGER;
2953
2954 ELSIF(sysPropName = RULE_SYS_PROP_MAXSELECTED)THEN
2955
2956 v_return(i) := TO_CHAR(glMaximumSel(optionIndex));
2957 ListType := DATA_TYPE_INTEGER;
2958
2959 ELSIF(sysPropName = RULE_SYS_PROP_MININSTANCE)THEN
2960
2961 IF(v_tExprSubtype(j) = 53)THEN
2962
2963 --For MinInstances and MaxInstances this is a fix for the bug #3558753.
2964
2965 --The reason we put two sets of MinInstances/MaxInstances was to support backward compatibility
2966 --of rules using those properties in the LHS. 53 and 54 are not mutable, thus they should not
2967 --be on the RHS (generic validation using the view already takes care of that). The remaining
2968 --part is to hard-code generating '0' for 53 (MinInstances) and '1' for 54 (MaxINstances).
2969 --(see also bug #4366895).
2970
2971 v_return(i) := '0';
2972 ELSE
2973
2974 v_return(i) := GENERATE_NAME(j, optionId)||'_MIN';
2975 END IF;
2976 ListType := DATA_TYPE_INTEGER;
2977
2978 ELSIF(sysPropName = RULE_SYS_PROP_MAXINSTANCE)THEN
2979
2980 IF(v_tExprSubtype(j) = 54)THEN
2981
2982 v_return(i) := '1';
2983 ELSE
2984
2985 v_return(i) := GENERATE_NAME(j, optionId)||'_MAX';
2986 END IF;
2987 ListType := DATA_TYPE_INTEGER;
2988
2989 ELSIF(sysPropName = RULE_SYS_PROP_STATE)THEN
2990
2991 v_return(i) := GENERATE_NAME(j, optionId);
2992 ListType := DATA_TYPE_BOOLEAN;
2993
2994 ELSIF(sysPropName = RULE_SYS_PROP_VALUE)THEN
2995
2996 v_return(i) := GENERATE_NAME(j, optionId);
2997 ListType := DATA_TYPE_VOID;
2998
2999 ELSIF(sysPropName = RULE_SYS_PROP_QUANTITY)THEN
3000
3001 v_return(i) := GENERATE_NAME(j, optionId);
3002 ListType := DATA_TYPE_INTEGER;
3003
3004 ELSIF(sysPropName = RULE_SYS_PROP_INSTANCECOUNT)THEN
3005
3006 IF(glPsNodeType(optionIndex) IN (PS_NODE_TYPE_COMPONENT,
3007 PS_NODE_TYPE_REFERENCE,
3008 PS_NODE_TYPE_PRODUCT))THEN
3009
3010 --If it is a non-virtual component/product/reference, we add _ACTUALCOUNT to the name.
3011 --If it is a virtual component/product/reference, we return '1'.
3012 --If it is an option, we just generate the name.
3013
3014 IF(glVirtualFlag(optionIndex) = FLAG_NON_VIRTUAL)THEN
3015 v_return(i) := GENERATE_NAME(j, optionId)||'_ACTUALCOUNT';
3016 ELSE
3017 v_return(i) := '1';
3018 END IF;
3019 ELSE
3020 v_return(i) := GENERATE_NAME(j, optionId);
3021 END IF;
3022
3023 ListType := DATA_TYPE_INTEGER;
3024 ELSE
3025
3026 RAISE CZ_E_NO_SUCH_PROPERTY;
3027 END IF;
3028 ELSE
3029
3030 BEGIN
3031
3032 itemId := glItemId(optionIndex);
3033
3034 v_return(i) := GET_PROPERTY_VALUE(optionId, propertyId, itemId, ListType);
3035
3036 IF(v_return(i) IS NULL)THEN RAISE CZ_E_NULL_PROPERTY_VALUE; END IF;
3037
3038 IF(ListType IN (DATA_TYPE_INTEGER, DATA_TYPE_DECIMAL))THEN
3039
3040 BEGIN
3041 nChild := TO_NUMBER(v_return(i));
3042 EXCEPTION
3043 WHEN OTHERS THEN
3044
3045 SELECT name INTO errorMessage
3046 FROM cz_properties
3047 WHERE property_id = propertyId;
3048
3049 localString := v_return(i);
3050 RAISE CZ_R_INCORRECT_DATA_TYPE;
3051 END;
3052 END IF;
3053
3054 EXCEPTION
3055 WHEN NO_DATA_FOUND THEN
3056 RAISE CZ_E_NO_SUCH_PROPERTY;
3057 WHEN TOO_MANY_ROWS THEN
3058 RAISE CZ_E_INCORRECT_PROPERTY;
3059 WHEN OTHERS THEN
3060 RAISE;
3061 END;
3062 END IF;
3063 END LOOP;
3064
3065 nDebug := 9001009;
3066
3067 RETURN v_return;
3068 END;
3069 ---------------------------------------------------------------------------------------
3070 FUNCTION GENERATE_PROPERTY(j IN PLS_INTEGER) RETURN tStringArray IS
3071 v_return tStringArray;
3072 ListType PLS_INTEGER;
3073 BEGIN
3074
3075 v_return(1) := PROPERTY_VALUE(j, glIndexByPsNodeId(v_tExprPsNodeId(j)), ListType);
3076 RETURN v_return;
3077 END;
3078 ---------------------------------------------------------------------------------------
3079 FUNCTION EXPAND_NODE_OPTIONAL(pvPsNodeId IN NUMBER) RETURN tIntegerArray IS --kdande; Bug 6881902; 11-Mar-2008
3080 v_return tIntegerArray;
3081 nCount PLS_INTEGER;
3082 nStartIndex PLS_INTEGER;
3083 nEndIndex PLS_INTEGER;
3084 indicator PLS_INTEGER := 0;
3085 BEGIN
3086
3087 nStartIndex := glIndexByPsNodeId(pvPsNodeId) + 1;
3088
3089 IF(NOT glLastChildIndex.EXISTS(pvPsNodeId))THEN
3090 localString := glName(glIndexByPsNodeId(pvPsNodeId));
3091 RAISE CZ_E_NO_EXPECTED_CHILDREN;
3092 END IF;
3093
3094 nEndIndex := glLastChildIndex(pvPsNodeId);
3095 nCount := 1;
3096
3097 IF(glPsNodeType(glIndexByPsNodeId(pvPsNodeId)) = PS_NODE_TYPE_FEATURE)THEN
3098
3099 indicator := 1;
3100 FOR i IN nStartIndex..nEndIndex LOOP
3101
3102 v_return(nCount) := i;
3103 nCount := nCount + 1;
3104
3105 END LOOP;
3106 ELSE
3107
3108 FOR i IN nStartIndex..nEndIndex LOOP
3109
3110 IF(glParentId(i) = pvPsNodeId AND glBomRequired(i) = FLAG_BOM_OPTIONAL)THEN
3111
3112 v_return(nCount) := i;
3113 nCount := nCount + 1;
3114
3115 END IF;
3116 END LOOP;
3117 END IF;
3118
3119 --Validate that there are any optional children, otherwise the rule has no sense so
3120 --just ignore it.
3121
3122 IF(v_return.COUNT = 0)THEN
3123 localString := glName(glIndexByPsNodeId(pvPsNodeId));
3124 IF(indicator = 1)THEN
3125 RAISE CZ_E_NO_EXPECTED_CHILDREN;
3126 END IF;
3127 RAISE CZ_E_NO_OPTIONAL_CHILDREN;
3128 END IF;
3129
3130 RETURN v_return;
3131 END;
3132 ---------------------------------------------------------------------------------------
3133 FUNCTION GENERATE_VAL(j IN PLS_INTEGER) RETURN tStringArray IS
3134 v_return tStringArray;
3135 nChild PLS_INTEGER;
3136 ListType PLS_INTEGER;
3137 nCheck NUMBER;
3138 BEGIN
3139
3140 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
3141 RAISE CZ_E_WRONG_VAL_EXPRESSION;
3142 END IF;
3143
3144 nChild := v_ChildrenIndex(v_tExprId(j));
3145 IF(v_tExprParentId.EXISTS(nChild + 1) AND v_tExprParentId(nChild + 1) = v_tExprId(j))THEN
3146 RAISE CZ_E_WRONG_VAL_EXPRESSION;
3147 END IF;
3148
3149 v_return := GENERATE_EXPRESSION(nChild, ListType);
3150
3151 BEGIN
3152 nCheck := TO_NUMBER(v_return(1));
3153 EXCEPTION
3154 WHEN OTHERS THEN
3155 RAISE CZ_E_WRONG_VAL_EXPRESS_TYPE;
3156 END;
3157
3158 RETURN v_return;
3159 END;
3160 ---------------------------------------------------------------------------------------
3161 FUNCTION GENERATE_LOGIC_SIDE(j IN PLS_INTEGER, Operator OUT NOCOPY PLS_INTEGER)
3162 RETURN tStringArray IS
3163 v_return tStringArray;
3164 ListType PLS_INTEGER := NEVER_EXISTS_ID;
3165 BEGIN
3166
3167 nDebug := 8001110;
3168
3169 --Removing the 'simple expression' branch as a part of the fix for the bug #3371279.
3170
3171 IF(v_tExprType(j) = EXPR_OPERATOR AND NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
3172
3173 RAISE CZ_R_INCOMPLETE_LOGIC_RULE;
3174 END IF;
3175
3176 v_return := GENERATE_EXPRESSION(j, ListType);
3177 Operator := OPERATOR_ALLOF;
3178 IF(ListType IN (OPERATOR_ANYOF, OPERATOR_ALLOF))THEN
3179 Operator := ListType;
3180 END IF;
3181 RETURN v_return;
3182 END;
3183 ---------------------------------------------------------------------------------------
3184 PROCEDURE GENERATE_LOGIC_RULE IS
3185 defaultName tStringArray;
3186 itemName tStringArray;
3187 v_lefts tStringArray;
3188 v_rights tStringArray;
3189 LeftOp PLS_INTEGER;
3190 RightOp PLS_INTEGER;
3191 ListType PLS_INTEGER;
3192 ObjectName VARCHAR2(16);
3193 BEGIN
3194
3195 IF(jAntecedentRoot IS NULL OR jConsequentRoot IS NULL)THEN
3196 RAISE CZ_R_INVALID_LOGIC_RULE;
3197 END IF;
3198
3199 nDebug := 8001100;
3200
3201 IF(nRuleOperator = RULE_OPERATOR_DEFAULTS)THEN
3202
3203 nDebug := 8001101;
3204
3205 defaultName := GENERATE_EXPRESSION(jAntecedentRoot, ListType);
3206 ListType := NEVER_EXISTS_ID;
3207 itemName := GENERATE_EXPRESSION(jConsequentRoot, ListType);
3208 IF(ListType NOT IN (OPERATOR_ANYOF, OPERATOR_ALLOF))THEN
3209 ListType := OPERATOR_ANYOF;
3210 END IF;
3211
3212 nDebug := 8001102;
3213
3214 localString := NULL;
3215 IF(itemName.COUNT > 1)THEN localString := sUnsatisfiedId; END IF;
3216
3217 nLocalDefaults := nLocalDefaults + 1;
3218 ObjectName := 'D_' || TO_CHAR(nLocalDefaults) || '_' || TO_CHAR(MaxDepthId);
3219
3220 vLogicLine := 'OBJECT ' || ObjectName || NewLine ||
3221 'WITH _default = ' || defaultName(1) || NewLine ||
3222 'GS R ' || localString || '... ' || TO_CHAR(nReasonId) || NewLine ||
3223 'GL' || OperatorLetters(ListType);
3224
3225 PACK;
3226
3227 nDebug := 8001103;
3228
3229 FOR i IN 1..itemName.COUNT LOOP
3230
3231 vLogicLine := itemName(i) || ' ';
3232 PACK;
3233
3234 END LOOP;
3235
3236 vLogicLine := NewLine || 'GR N ' || ObjectName || NewLine;
3237 PACK;
3238
3239 nDebug := 8001104;
3240
3241 ELSE
3242
3243 nDebug := 8001105;
3244
3245 v_lefts := GENERATE_LOGIC_SIDE(jAntecedentRoot, LeftOp);
3246 v_rights := GENERATE_LOGIC_SIDE(jConsequentRoot, RightOp);
3247
3248 nDebug := 8001106;
3249
3250 localString := NULL;
3251 IF(v_lefts.COUNT > 1 OR v_rights.COUNT > 1)THEN localString := sUnsatisfiedId; END IF;
3252
3253 vLogicLine := 'GS' || OperatorLetters(nRuleOperator) || localString || '... ' || TO_CHAR(nReasonId) || NewLine ||
3254 'GL' || OperatorLetters(LeftOp);
3255 PACK;
3256
3257 nDebug := 8001107;
3258
3259 FOR i IN 1..v_lefts.COUNT LOOP
3260
3261 vLogicLine := v_lefts(i) || ' ';
3262 PACK;
3263
3264 END LOOP;
3265
3266 nDebug := 8001108;
3267
3268 vLogicLine := NewLine || 'GR' || OperatorLetters(RightOp);
3269 PACK;
3270
3271 FOR i IN 1..v_rights.COUNT LOOP
3272
3273 vLogicLine := v_rights(i) || ' ';
3274 PACK;
3275
3276 END LOOP;
3277
3278 vLogicLine := NewLine;
3279 PACK;
3280
3281 nDebug := 8001109;
3282
3283 END IF;
3284 END;
3285 ---------------------------------------------------------------------------------------
3286 FUNCTION HAS_INTEGER_VALUE(j IN PLS_INTEGER) RETURN PLS_INTEGER IS
3287 NodeType PLS_INTEGER := v_tExprType(j);
3288 FeatureType PLS_INTEGER;
3289 SysPropType PLS_INTEGER;
3290 PsNodeIndex PLS_INTEGER;
3291 BEGIN
3292
3293 IF(NodeType = EXPR_ARGUMENT)THEN
3294
3295 PsNodeIndex := LOOKUP_ARGUMENT(j);
3296 IF(parameterScope(PsNodeIndex).node_id IS NULL)THEN RETURN GENERATE_SCOPE_ERROR; END IF;
3297
3298 NodeType := EXPR_PSNODE;
3299 v_tExprPsNodeId(j) := parameterScope(PsNodeIndex).node_id;
3300 END IF;
3301
3302 IF(NodeType = EXPR_PSNODE)THEN
3303
3304 NodeType := glPsNodeType(glIndexByPsNodeId(v_tExprPsNodeId(j)));
3305 FeatureType := glFeatureType(glIndexByPsNodeId(v_tExprPsNodeId(j)));
3306 localString := glName(glIndexByPsNodeId(v_tExprPsNodeId(j)));
3307
3308 IF(NodeType = PS_NODE_TYPE_FEATURE AND FeatureType IN
3309 (PS_NODE_FEATURE_TYPE_OPTION, PS_NODE_FEATURE_TYPE_BOOLEAN)
3310 AND (NOT v_ChildrenIndex.EXISTS(v_tExprId(j))))THEN
3311
3312 IF(FeatureType = PS_NODE_FEATURE_TYPE_OPTION)THEN
3313 errorMessage := 'Option Feature';
3314 ELSE
3315 errorMessage := 'Boolean Feature';
3316 END IF;
3317 RAISE CZ_R_INCORRECT_NUMERIC_RHS;
3318 ELSIF(NodeType = PS_NODE_TYPE_COMPONENT AND (NOT v_ChildrenIndex.EXISTS(v_tExprId(j))))THEN
3319
3320 --Bug #3800339. This is a component without a system property applied. As the data is corrupted,
3321 --it may not be possible to catch things like that by queries against the seed data.
3322
3323 errorMessage := 'Component';
3324 RAISE CZ_R_INCORRECT_NUMERIC_RHS;
3325 END IF;
3326
3327 IF(v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
3328 IF(v_tExprType(v_ChildrenIndex(v_tExprId(j))) = EXPR_PROP)THEN
3329
3330 --User properties are not allowed in the consequent expression.
3331
3332 RAISE CZ_R_INVALID_NUMERIC_RULE;
3333 END IF;
3334
3335 SysPropType := v_tExprSubtype(v_ChildrenIndex(v_tExprId(j)));
3336 IF(NOT h_SeededName.EXISTS(SysPropType))THEN RAISE CZ_E_BAD_PROPERTY_TYPE; END IF;
3337
3338 IF(h_SeededName(SysPropType) = RULE_SYS_PROP_SELECTION)THEN RETURN GENERATE_DYNAMIC; END IF;
3339
3340 IF(h_SeededName(SysPropType) <> RULE_SYS_PROP_SELECTION AND
3341 (NOT APPLICABLE_SYS_PROP(j, NULL, SysPropType)))THEN
3342
3343 localString := h_ReportName(sysPropType);
3344 auxIndex := glIndexByPsNodeId(v_tExprPsNodeId(j));
3345 RAISE CZ_R_INCOMPATIBLE_SYSPROP;
3346 ELSE
3347
3348 --Bug #4677027. No rounding operator for contributions to any bom nodes.
3349
3350 IF(NodeType IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN RETURN GENERATE_CONTRIBUTE; END IF;
3351
3352 IF(COMPATIBLE_DATA_TYPES(SIGNATURE_DATA_TYPE(h_SignatureId(SysPropType)), DATATYPE_INTEGER))THEN
3353 RETURN GENERATE_INCREMENT;
3354 END IF;
3355 END IF;
3356 ELSE
3357 IF(NodeType = PS_NODE_TYPE_OPTION OR
3358 (NodeType = PS_NODE_TYPE_FEATURE AND FeatureType = PS_NODE_FEATURE_TYPE_INTEGER))THEN
3359 RETURN GENERATE_INCREMENT;
3360 END IF;
3361 END IF;
3362 RETURN GENERATE_CONTRIBUTE;
3363 ELSE
3364 RETURN GENERATE_CONTRIBUTE;
3365 END IF;
3366 END;
3367 ---------------------------------------------------------------------------------------
3368 FUNCTION GENERATE_NUMERIC_PART(j IN PLS_INTEGER, NodeId IN OUT NOCOPY NUMBER) --kdande; Bug 6881902; 11-Mar-2008
3369 RETURN VARCHAR2 IS
3370 ExprType PLS_INTEGER := v_tExprType(j);
3371 v_return VARCHAR2(4000);
3372 v_propval tStringArray;
3373 ListType PLS_INTEGER;
3374 nChild NUMBER;
3375 BEGIN
3376 IF(ExprType IN (EXPR_PSNODE, EXPR_ARGUMENT))THEN
3377
3378 v_propval := GENERATE_EXPRESSION(j, ListType);
3379 v_return := v_propval(1);
3380 NodeId := v_tExprPsNodeId(j);
3381
3382 ELSIF(ExprType = EXPR_NODE_TYPE_COUNT)THEN
3383
3384 v_return := GENERATE_NAME(j, v_tExprPsNodeId(j));
3385 NodeId := v_tExprPsNodeId(j);
3386
3387 ELSIF(ExprType = EXPR_NODE_TYPE_LITERAL)THEN
3388
3389 v_return := v_tExprDataValue(j);
3390 NodeId := 0;
3391
3392 ELSIF(ExprType = EXPR_NODE_TYPE_PROP)THEN
3393
3394 v_return := PROPERTY_VALUE(j, glIndexByPsNodeId(NodeId), ListType);
3395 NodeId := 0;
3396
3397 BEGIN
3398 nChild := TO_NUMBER(v_return);
3399 IF(nChild = 0)THEN NodeId := -1; END IF;
3400 EXCEPTION
3401 WHEN OTHERS THEN
3402
3403 SELECT name INTO errorMessage
3404 FROM cz_properties
3405 WHERE property_id = v_tExprPropertyId(j);
3406
3407 RAISE CZ_R_INCORRECT_NUMERICLHS;
3408 END;
3409
3410 ELSIF(ExprType = EXPR_NODE_TYPE_OPERATOR AND v_tExprSubtype(j) = OPERATOR_DOT)THEN
3411
3412 nChild := v_ChildrenIndex(v_tExprId(j));
3413 v_tExplNodeId(nChild + 1) := v_tExplNodeId(nChild);
3414 v_return := PROPERTY_VALUE(nChild + 1, glIndexByPsNodeId(v_tExprPsNodeId(nChild)), ListType);
3415 NodeId := v_tExprPsNodeId(nChild);
3416
3417 ELSE
3418
3419 RAISE CZ_R_INVALID_NUMERIC_PART;
3420
3421 END IF;
3422 RETURN v_return;
3423 END;
3424 ---------------------------------------------------------------------------------------
3425 FUNCTION GENERATE_BOOLEAN_PART(j IN PLS_INTEGER) RETURN VARCHAR2 IS
3426 nChild PLS_INTEGER;
3427 v_return VARCHAR2(4000);
3428 v_index tIntegerArray;
3429 ExprId NUMBER := v_tExprId(j); --Bug13566997
3430 BEGIN
3431
3432 nDebug := 8001001;
3433
3434 nChild := v_ChildrenIndex(ExprId);
3435
3436 nDebug := 8001002;
3437
3438 nLocalDefaults := nLocalDefaults + 1;
3439 v_return := t_prefix || TO_CHAR(nLocalDefaults);
3440
3441 vLogicLine := 'OBJECT ' || v_return || NewLine ||
3442 'GS R ... ' || TO_CHAR(nReasonId) || NewLine ||
3443 'GL' || OperatorLetters(v_tExprSubtype(j));
3444 PACK;
3445
3446 nDebug := 8001004;
3447
3448 WHILE(v_tExprParentId(nChild) = ExprId) LOOP
3449
3450 v_index := EXPAND_NODE(nChild);
3451
3452 FOR i IN 1..v_index.COUNT LOOP
3453
3454 vLogicLine := GENERATE_NAME_EXPL(v_ExplByPsNodeId(v_index(i)), v_index(i)) || ' ';
3455 PACK;
3456 END LOOP;
3457
3458 nChild := nChild + 1;
3459 END LOOP;
3460
3461 nDebug := 8001005;
3462
3463 vLogicLine := NewLine || 'GR' || OperatorLetters(OPERATOR_ALLOF) || v_return || NewLine;
3464 PACK;
3465
3466 nDebug := 8001006;
3467
3468 RETURN v_return;
3469 END;
3470 ---------------------------------------------------------------------------------------
3471 PROCEDURE GENERATE_INCREMENT_LOGIC IS
3472 v_NodeId NUMBER; --kdande; Bug 6881902; 11-Mar-2008
3473 v_HeaderId NUMBER;
3474 v_return VARCHAR2(4000);
3475 v_result tStringArray;
3476 v_index tStringArray;
3477 v_acname VARCHAR2(4000);
3478 v_nodename VARCHAR2(4000);
3479 v_accuname VARCHAR2(4000);
3480 ListType PLS_INTEGER;
3481 sSign VARCHAR2(8) := NULL;
3482 lhsNode PLS_INTEGER := 0;
3483 rhsNode PLS_INTEGER := 0;
3484 lhsName VARCHAR2(4000);
3485 rhsName VARCHAR2(4000);
3486 nOpNode PLS_INTEGER;
3487 nChild PLS_INTEGER;
3488 nGrandChild PLS_INTEGER;
3489 nSuffix PLS_INTEGER := 0;
3490 iLocal PLS_INTEGER;
3491 operatorLiteral VARCHAR2(4000);
3492 v_name VARCHAR2(128);
3493 ---------------------------------------------------------------------------------------
3494 PROCEDURE GENERATE_INCREMENT_RECORD IS
3495 v_total VARCHAR2(4000) := NULL;
3496 BEGIN
3497
3498 IF(v_tExprSubtype(nOpNode) = OPERATOR_DIV)THEN
3499
3500 v_total := t_prefix || v_name || '_' || TO_CHAR(nSuffix);
3501 vLogicLine := 'TOTAL ' || v_total || NewLine ||
3502 'CONTRIBUTE ' || lhsName || OperatorLiterals(OPERATOR_DIV) ||
3503 rhsName || ' ' || v_total || ' ... ' || TO_CHAR(nReasonId) || NewLine;
3504 PACK;
3505 ELSIF(v_tExprSubtype(nOpNode) = OPERATOR_MATHDIV)THEN
3506
3507 v_total := t_prefix || v_name || '_' || TO_CHAR(nSuffix);
3508 vLogicLine := 'TOTAL ' || v_total || NewLine ||
3509 'MF ' || lhsName || ' ' || rhsName || OperatorLiterals(OPERATOR_MATHDIV) ||
3510 v_total || ' ... ' || TO_CHAR(nReasonId) || NewLine;
3511 PACK;
3512 END IF;
3513
3514 sSign := NULL;
3515 IF(nRuleOperator = RULE_OPERATOR_CONSUMES)THEN
3516 sSign := '-1 ';
3517 END IF;
3518
3519 IF(v_total IS NULL)THEN
3520
3521 vLogicLine := 'INC ' || sSign || lhsName || ' ' || rhsName || ' ' || v_acname ||
3522 OperatorLiteral || '... ' || TO_CHAR(nReasonId) || NewLine;
3523
3524 ELSE
3525
3526 vLogicLine := 'INC ' || sSign || v_total || ' ' || v_acname ||
3527 OperatorLiteral || '... ' || TO_CHAR(nReasonId) || NewLine;
3528
3529 END IF;
3530 PACK;
3531 END;
3532 ---------------------------------------------------------------------------------------
3533 BEGIN
3534
3535 nLocalDefaults := nLocalDefaults + 1;
3536 v_name := TO_CHAR(nLocalDefaults);
3537
3538 --Generate the accumulator and corresponding increment relation if necessary
3539
3540 nDebug := 8001200;
3541
3542 v_return := GENERATE_NUMERIC_PART(jConsequentRoot, v_NodeId);
3543
3544 nDebug := 8001201;
3545
3546 IF(v_tExprType(jConsequentRoot) = EXPR_NODE_TYPE_OPERATOR AND
3547 v_tExprSubtype(jConsequentRoot) = OPERATOR_DOT)THEN
3548
3549 nDebug := 8001202;
3550
3551 nChild := v_ChildrenIndex(v_tExprId(jConsequentRoot)) + 1;
3552 v_acname := v_return;
3553
3554 --Commenting the following block out as the fix to bug #1657701. Assuming that this code
3555 --was necessary until some fixes in participants' model_ref_expl_id population hadn't
3556 --been done, and now it's obsolete.
3557 /*
3558 IF(v_NodeId = v_tPsNodeId(v_IndexByNodeId(MaxDepthId)))THEN
3559 v_acname := PATH_DELIMITER || 'parent' || PATH_DELIMITER || v_acname;
3560 END IF;
3561 */
3562
3563 ELSIF(v_tExprType(jConsequentRoot) = EXPR_PSNODE AND v_ChildrenIndex.EXISTS(v_tExprId(jConsequentRoot)))THEN
3564
3565 nChild := jConsequentRoot;
3566 v_acname := v_return;
3567
3568 ELSIF((NOT v_HeaderByAccId.EXISTS(v_NodeId)) AND
3569 (glAccumulator(v_NodeId) IS NULL OR glAccumulator(v_NodeId) = FLAG_NO_ACCUMULATOR))THEN
3570
3571 nDebug := 8001203;
3572
3573 v_HeaderId := glHeaderByPsNodeId(v_NodeId);
3574 v_nodename := 'P_' || TO_CHAR(glPersistentId(v_NodeId));
3575 v_accuname := v_nodename || '_ACC';
3576
3577 --Flush off the buffer because we are about to write to another file
3578
3579 IF(vLogicText IS NOT NULL)THEN
3580 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
3581 (nHeaderId, v_tSequenceNbr(nHeaderId), vLogicText);
3582 vLogicText := NULL;
3583 v_tSequenceNbr(nHeaderId) := v_tSequenceNbr(nHeaderId) + 1;
3584 END IF;
3585
3586 --Fix for the bug #2398832 - we may be re-using the accumulator, so we should not
3587 --assign to it effectivities and usages of a particular node.
3588 --Do not write the effectivity dates using the actual effective date interval of
3589 --the corresponding node.
3590
3591 --iLocal := glIndexByPsNodeId(v_NodeId);
3592 --CurrentEffFrom := glEffFrom(iLocal);
3593 --CurrentEffUntil := glEffUntil(iLocal);
3594 --CurrentUsageMask := glUsageMask(iLocal);
3595
3596 --Instead make the accumulator always effective and universal.
3597
3598 CurrentEffFrom := EpochBeginDate;
3599 CurrentEffUntil := EpochEndDate;
3600 CurrentUsageMask := AnyUsageMask;
3601
3602 IF((NOT h_EffFrom.EXISTS(v_HeaderId)) OR
3603 (h_EffFrom(v_HeaderId) <> CurrentEffFrom OR h_EffUntil(v_HeaderId) <> CurrentEffUntil OR
3604 h_EffUsageMask(v_HeaderId) <> CurrentUsageMask))THEN
3605
3606 h_EffFrom(v_HeaderId) := CurrentEffFrom;
3607 h_EffUntil(v_HeaderId) := CurrentEffUntil;
3608 h_EffUsageMask(v_HeaderId) := CurrentUsageMask;
3609
3610 vLogicText := LTRIM(CurrentUsageMask, '0');
3611 IF(vLogicText IS NOT NULL) THEN
3612 vLogicText := EffUsagePrefix || vLogicText;
3613 END IF;
3614
3615 IF(CurrentEffFrom = EpochBeginDate)THEN
3616 CurrentFromDate := NULL;
3617 ELSE
3618 CurrentFromDate := TO_CHAR(CurrentEffFrom, EffDateFormat);
3619 END IF;
3620
3621 IF(CurrentEffUntil = EpochEndDate)THEN
3622 CurrentUntilDate := NULL;
3623 ELSE
3624 CurrentUntilDate := TO_CHAR(CurrentEffUntil, EffDateFormat);
3625 END IF;
3626
3627 vLogicText := 'EFF ' || CurrentFromDate || ', ' || CurrentUntilDate || ', ' || vLogicText || NewLine;
3628 END IF;
3629
3630 vLogicText := vLogicText || 'TOTAL ' || v_accuname || NewLine ||
3631 'INC ' || v_accuname || ' ' || v_nodename ||
3632 OperatorLiterals(OPERATOR_ROUND) || '... ' || TO_CHAR(nReasonId) || NewLine;
3633
3634 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
3635 (v_HeaderId, vSeqNbrByHeader(v_HeaderId), vLogicText);
3636 vLogicText := NULL;
3637 vSeqNbrByHeader(v_HeaderId) := vSeqNbrByHeader(v_HeaderId) + 1;
3638
3639 v_HeaderByAccId(v_NodeId) := v_HeaderId;
3640 v_acname := v_return || '_ACC';
3641
3642 --Part of the fix for the bug #2857955. We will never be here if glAccumulator(v_NodeId) was
3643 --FLAG_ACCUMULATOR_ACC because the accumulator would have already been created.
3644
3645 UPDATE cz_ps_nodes SET
3646 accumulator_flag = DECODE(glAccumulator(v_NodeId), FLAG_ACCUMULATOR_NT, FLAG_ACCUMULATOR_BOTH, FLAG_ACCUMULATOR_ACC)
3647 WHERE ps_node_id = v_NodeId;
3648
3649 ELSE
3650
3651 nDebug := 8001204;
3652
3653 v_acname := v_return || '_ACC';
3654 END IF;
3655
3656 nDebug := 8001205;
3657
3658 --If we are here, than the RHS expression has an integer value and so the LHS expression
3659 --should have a root rounding operator. So go down one level.
3660 --However, as a fix for the bug #3558699 we now don't require the root rounding operator
3661 --if the data type of antecedent is convertible to integer. Therefore we have to be more
3662 --flexible here.
3663
3664 IF(v_tExprType(jAntecedentRoot) <> EXPR_OPERATOR OR v_tExprSubtype(jAntecedentRoot) NOT IN
3665 (OPERATOR_ROUND, OPERATOR_CEILING, OPERATOR_FLOOR, OPERATOR_TRUNCATE, OPERATOR_NONE))THEN
3666 nOpNode := jAntecedentRoot;
3667 OperatorLiteral := OperatorLiterals(OPERATOR_NONE);
3668 ELSE
3669 nOpNode := v_ChildrenIndex(v_tExprId(jAntecedentRoot));
3670 OperatorLiteral := OperatorLiterals(v_tExprSubtype(jAntecedentRoot));
3671 END IF;
3672
3673 IF(v_tExprType(nOpNode) = EXPR_OPERATOR AND (NOT v_ChildrenIndex.EXISTS(v_tExprId(nOpNode))))THEN
3674 RAISE CZ_R_INCOMPLETE_NUMERIC_RULE;
3675 END IF;
3676
3677 IF(v_ChildrenIndex.EXISTS(v_tExprId(nOpNode)))THEN
3678 lhsNode := v_ChildrenIndex(v_tExprId(nOpNode));
3679 rhsNode := lhsNode + v_NumberOfChildren(v_tExprId(nOpNode)) - 1;
3680 END IF;
3681
3682 IF(nPresentationFlag = FLAG_FREEFORM_RULE)THEN
3683
3684 --Check if this is a simple numeric rule that has been upgraded to become a free-form rule. For such
3685 --rules we want to generate an optimized INC relation.
3686 --Bug #4047086. However, the operator can only be multiplication to be able to optimize.
3687 --Bugs #4256960, #4254591. The RHS operand must also be simple, not an operator.
3688
3689 IF((v_tExprType(nOpNode) = EXPR_OPERATOR AND v_tExprSubtype(nOpNode) = OPERATOR_MULT) AND
3690 (v_tExprType(rhsNode) <> EXPR_OPERATOR) AND (v_tExprType(lhsNode) = EXPR_LITERAL OR
3691 (v_tExprType(lhsNode) IN (EXPR_PSNODE, EXPR_ARGUMENT) AND (NOT HAS_OPTIONS_APPLIED(lhsNode)))))THEN
3692
3693 rhsNode := lhsNode + 1;
3694
3695 lhsName := GENERATE_NUMERIC_PART(lhsNode, v_NodeId);
3696 rhsName := GENERATE_NUMERIC_PART(rhsNode, v_NodeId);
3697 GENERATE_INCREMENT_RECORD;
3698 RETURN;
3699 ELSE
3700
3701 nDebug := 8001206;
3702
3703 numericLHS := 1;
3704 v_result := GENERATE_EXPRESSION(nOpNode, ListType);
3705 IF(nRuleOperator = RULE_OPERATOR_CONSUMES)THEN
3706 sSign := '-1 ';
3707 END IF;
3708 vLogicLine := 'INC ' || sSign || v_result(1) || ' ' || v_acname ||
3709 OperatorLiteral || '... ' || TO_CHAR(nReasonId) || NewLine;
3710 PACK;
3711 RETURN;
3712 END IF;
3713 END IF;
3714
3715 nDebug := 8001207;
3716
3717 FOR i IN lhsNode..rhsNode - 1 LOOP
3718 IF(v_tExprType(i) = EXPR_PSNODE AND HAS_OPTIONS_APPLIED(i))THEN
3719
3720 v_index := GENERATE_CHILDRENOF(v_tExplNodeId(i), v_tExprPsNodeId(i));
3721
3722 FOR ich IN 1..v_index.COUNT LOOP
3723
3724 lhsName := v_index(ich);
3725 rhsName := GENERATE_NUMERIC_PART(rhsNode, v_NodeId);
3726 GENERATE_INCREMENT_RECORD;
3727 nSuffix := nSuffix + 1;
3728 END LOOP;
3729 ELSIF(v_tExprType(i) IN (EXPR_LITERAL, EXPR_PSNODE))THEN
3730
3731 lhsName := GENERATE_NUMERIC_PART(i, v_NodeId);
3732 v_NodeId := v_tExprPsNodeId(i);
3733 rhsName := GENERATE_NUMERIC_PART(rhsNode, v_NodeId);
3734
3735 GENERATE_INCREMENT_RECORD;
3736 nSuffix := nSuffix + 1;
3737 ELSE
3738
3739 RAISE CZ_R_INVALID_NUMRULE_NODE;
3740 END IF;
3741 END LOOP;
3742 END;
3743 ---------------------------------------------------------------------------------------
3744 PROCEDURE GENERATE_CONTRIBUTE_LOGIC IS
3745 v_return VARCHAR2(4000);
3746 v_result tStringArray;
3747 v_index tStringArray;
3748 ListType PLS_INTEGER;
3749 sSign VARCHAR2(8);
3750 lhsNode PLS_INTEGER;
3751 rhsNode PLS_INTEGER;
3752 lhsName VARCHAR2(4000);
3753 rhsName VARCHAR2(4000);
3754 nChild PLS_INTEGER;
3755 nGrandChild PLS_INTEGER;
3756 v_NodeId NUMBER; --kdande; Bug 6881902; 11-Mar-2008
3757 nSuffix PLS_INTEGER := 0;
3758 nOpNode PLS_INTEGER := jAntecedentRoot;
3759 sOpRoot VARCHAR2(16):= ' ';
3760 v_HeaderId NUMBER;
3761 v_nodename VARCHAR2(4000);
3762 v_accuname VARCHAR2(4000);
3763 iLocal PLS_INTEGER;
3764 v_name VARCHAR2(128);
3765 ---------------------------------------------------------------------------------------
3766 PROCEDURE GENERATE_CONTRIBUTE_RECORD IS
3767 v_total VARCHAR2(4000);
3768 v_local VARCHAR2(4000) := v_return;
3769 BEGIN
3770 IF(nRuleOperator = RULE_OPERATOR_CONSUMES)THEN
3771
3772 v_total := t_prefix || v_name || '_' || TO_CHAR(nSuffix);
3773 vLogicLine := 'TOTAL ' || v_total || NewLine ||
3774 'CONTRIBUTE ' || v_total || OperatorLiterals(OPERATOR_MULT) ||
3775 '-1 ' || v_local || ' ... ' || TO_CHAR(nReasonId) || NewLine;
3776 v_local := v_total;
3777 PACK;
3778 END IF;
3779
3780 IF(v_NodeId = -1 AND v_tExprSubtype(nOpNode) = OPERATOR_MULT)THEN
3781
3782 vLogicLine := 'CONTRIBUTE ' || lhsName || OperatorLiterals(OPERATOR_SUB) ||
3783 lhsName || ' ' || v_local || sOpRoot || '... ' || TO_CHAR(nReasonId) || NewLine;
3784 ELSIF(v_tExprSubtype(nOpNode) = OPERATOR_MATHDIV)THEN
3785
3786 v_total := t_prefix || v_name || '_' || TO_CHAR(nSuffix);
3787 vLogicLine := 'TOTAL ' || v_total || NewLine ||
3788 'MF ' || lhsName || ' ' || rhsName || OperatorLiterals(OPERATOR_MATHDIV) ||
3789 v_total || ' ... ' || TO_CHAR(nReasonId) || NewLine;
3790 PACK;
3791 vLogicLine := 'CONTRIBUTE 1 ' || v_total || ' ' || v_local || sOpRoot || '... ' || TO_CHAR(nReasonId) || NewLine;
3792 ELSE
3793
3794 vLogicLine := 'CONTRIBUTE ' || lhsName || OperatorLiterals(v_tExprSubtype(nOpNode)) ||
3795 rhsName || ' ' || v_local || sOpRoot || '... ' || TO_CHAR(nReasonId) || NewLine;
3796 END IF;
3797 PACK;
3798 END;
3799 ---------------------------------------------------------------------------------------
3800 BEGIN
3801
3802 nLocalDefaults := nLocalDefaults + 1;
3803 v_name := TO_CHAR(nLocalDefaults);
3804
3805 nDebug := 8002;
3806
3807 v_return := GENERATE_NUMERIC_PART(jConsequentRoot, v_NodeId);
3808 optimizeChain := OPTIMIZATION_UNKNOWN;
3809 optimizeContribute := OPTIMIZATION_UNKNOWN;
3810
3811 IF(v_tLogicNetType(nHeaderId) = LOGIC_NET_TYPE_NETWORK AND
3812 glPsNodeType(glIndexByPsNodeId(v_NodeId)) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
3813
3814 --This is a conditional numeric rule against a BOM node. We will create an accumulator and
3815 --a 'contribute' relation from the accumulator to the BOM object, if such accumulator does
3816 --not exist. We'll need to temporarily switch context to the BOM object's structure file.
3817
3818 IF((NOT v_HeaderByAccId.EXISTS(v_NodeId)) AND
3819 (glAccumulator(v_NodeId) IS NULL OR glAccumulator(v_NodeId) = FLAG_NO_ACCUMULATOR))THEN
3820
3821 --Retrieve the corresponding structure file header and prepare the names.
3822
3823 v_HeaderId := glHeaderByPsNodeId(v_NodeId);
3824 v_nodename := 'P_' || TO_CHAR(glPersistentId(v_NodeId));
3825 v_accuname := v_nodename || '_ACC';
3826
3827 --Flush off the buffer because we are about to write to another file.
3828
3829 IF(vLogicText IS NOT NULL)THEN
3830 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
3831 (nHeaderId, v_tSequenceNbr(nHeaderId), vLogicText);
3832 vLogicText := NULL;
3833 v_tSequenceNbr(nHeaderId) := v_tSequenceNbr(nHeaderId) + 1;
3834 END IF;
3835
3836 --Fix for the bug #2398832 - we may be re-using the accumulator, so we should not
3837 --assign to it effectivities and usages of a particular node.
3838 --Do not write the effectivity dates using the actual effective date interval of
3839 --the corresponding node.
3840
3841 --iLocal := glIndexByPsNodeId(v_NodeId);
3842 --CurrentEffFrom := glEffFrom(iLocal);
3843 --CurrentEffUntil := glEffUntil(iLocal);
3844 --CurrentUsageMask := glUsageMask(iLocal);
3845
3846 --Instead make the accumulator always effective and universal.
3847
3848 CurrentEffFrom := EpochBeginDate;
3849 CurrentEffUntil := EpochEndDate;
3850 CurrentUsageMask := '0';
3851
3852 IF((NOT h_EffFrom.EXISTS(v_HeaderId)) OR
3853 (h_EffFrom(v_HeaderId) <> CurrentEffFrom OR h_EffUntil(v_HeaderId) <> CurrentEffUntil OR
3854 h_EffUsageMask(v_HeaderId) <> CurrentUsageMask))THEN
3855
3856 h_EffFrom(v_HeaderId) := CurrentEffFrom;
3857 h_EffUntil(v_HeaderId) := CurrentEffUntil;
3858 h_EffUsageMask(v_HeaderId) := CurrentUsageMask;
3859
3860 vLogicText := LTRIM(CurrentUsageMask, '0');
3861 IF(vLogicText IS NOT NULL) THEN
3862 vLogicText := EffUsagePrefix || vLogicText;
3863 END IF;
3864
3865 IF(CurrentEffFrom = EpochBeginDate)THEN
3866 CurrentFromDate := NULL;
3867 ELSE
3868 CurrentFromDate := TO_CHAR(CurrentEffFrom, EffDateFormat);
3869 END IF;
3870
3871 IF(CurrentEffUntil = EpochEndDate)THEN
3872 CurrentUntilDate := NULL;
3873 ELSE
3874 CurrentUntilDate := TO_CHAR(CurrentEffUntil, EffDateFormat);
3875 END IF;
3876
3877 vLogicText := 'EFF ' || CurrentFromDate || ', ' || CurrentUntilDate || ', ' || vLogicText || NewLine;
3878 END IF;
3879
3880 --Write the logic record in the structure file.
3881
3882 vLogicText := vLogicText || 'TOTAL ' || v_accuname || NewLine ||
3883 'CONTRIBUTE 1 ' || v_accuname || ' ' || v_nodename ||
3884 ' ... ' || TO_CHAR(nReasonId) || NewLine;
3885
3886 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
3887 (v_HeaderId, vSeqNbrByHeader(v_HeaderId), vLogicText);
3888
3889 vLogicText := NULL;
3890 vSeqNbrByHeader(v_HeaderId) := vSeqNbrByHeader(v_HeaderId) + 1;
3891 v_HeaderByAccId(v_NodeId) := v_HeaderId;
3892
3893 --This line and the ELSE branch below are to fix the bug #2702587 - we need not only create the
3894 --accumulator and a relation for it to the object but we also need to generate the rule so that
3895 --it contributes to the accumulator, not the objects.
3896
3897 v_return := v_return || '_ACC';
3898
3899 --Part of the fix for the bug #2857955. We will never be here if glAccumulator(v_NodeId) was
3900 --FLAG_ACCUMULATOR_ACC because the accumulator would have already been created.
3901
3902 UPDATE cz_ps_nodes SET
3903 accumulator_flag = DECODE(glAccumulator(v_NodeId), FLAG_ACCUMULATOR_NT, FLAG_ACCUMULATOR_BOTH, FLAG_ACCUMULATOR_ACC)
3904 WHERE ps_node_id = v_NodeId;
3905
3906 ELSE
3907
3908 v_return := v_return || '_ACC';
3909 END IF;
3910 END IF;
3911
3912 nDebug := 8003;
3913
3914 IF(v_tExprSubtype(jAntecedentRoot) IN
3915 (OPERATOR_ROUND, OPERATOR_FLOOR, OPERATOR_CEILING, OPERATOR_TRUNCATE, OPERATOR_NONE))THEN
3916 nOpNode := v_ChildrenIndex(v_tExprId(jAntecedentRoot));
3917 sOpRoot := OperatorLiterals(v_tExprSubtype(jAntecedentRoot));
3918 END IF;
3919
3920 IF(nPresentationFlag = FLAG_FREEFORM_RULE)THEN
3921
3922 nDebug := 8004;
3923
3924 IF(nRuleOperator = RULE_OPERATOR_CONTRIBUTES)THEN
3925
3926 sSign := '1 ';
3927
3928 --If this is a numeric contribute rule with a root rounding operator, set the flag and store
3929 --the target from the Motorola optimization (bug #2540163).
3930
3931 IF(v_tExprSubtype(jAntecedentRoot) IN
3932 (OPERATOR_ROUND, OPERATOR_FLOOR, OPERATOR_CEILING, OPERATOR_TRUNCATE))THEN
3933
3934 optimizeChain := OPTIMIZATION_REQUESTED;
3935 optimizeTarget := v_return;
3936 ELSE
3937
3938 optimizeContribute := OPTIMIZATION_REQUESTED;
3939 END IF;
3940 ELSE
3941
3942 sSign := '-1 ';
3943 END IF;
3944
3945 nDebug := 8004001;
3946
3947 numericLHS := 1;
3948 v_result := GENERATE_EXPRESSION(jAntecedentRoot, ListType);
3949
3950 --The value may have been changed during the expression generation. If it is not 0, we still
3951 --want to generate the rule's contribute relation. However, if it is 0 than the relation has
3952 --already been generated as a part of the optimization so here we just skip it.
3953
3954 IF(optimizeChain IN (OPTIMIZATION_REQUESTED, OPTIMIZATION_UNKNOWN))THEN
3955 IF(optimizeContribute = OPTIMIZATION_COMPLETED)THEN
3956
3957 vLogicLine := 'CONTRIBUTE ' || v_result(1) || v_return || ' ... ' || TO_CHAR(nReasonId) || NewLine;
3958 ELSE
3959
3960 vLogicLine := 'CONTRIBUTE ' || v_result(1) || OperatorLiterals(OPERATOR_MULT) ||
3961 sSign || v_return || sOpRoot || '... ' || TO_CHAR(nReasonId) || NewLine;
3962 END IF;
3963
3964 PACK;
3965 optimizeChain := OPTIMIZATION_UNKNOWN;
3966 END IF;
3967
3968 RETURN;
3969 END IF;
3970
3971 nDebug := 8005;
3972
3973 lhsNode := v_ChildrenIndex(v_tExprId(nOpNode));
3974 rhsNode := lhsNode + v_NumberOfChildren(v_tExprId(nOpNode)) - 1;
3975
3976 nDebug := 8006;
3977
3978 FOR i IN lhsNode..rhsNode - 1 LOOP
3979
3980 IF(v_tExprType(i) = EXPR_PSNODE AND HAS_OPTIONS_APPLIED(i))THEN
3981
3982 v_index := GENERATE_CHILDRENOF(v_tExplNodeId(i), v_tExprPsNodeId(i));
3983
3984 FOR ich IN 1..v_index.COUNT LOOP
3985
3986 lhsName := v_index(ich);
3987 rhsName := GENERATE_NUMERIC_PART(rhsNode, v_NodeId);
3988
3989 GENERATE_CONTRIBUTE_RECORD;
3990 nSuffix := nSuffix + 1;
3991 END LOOP;
3992 ELSIF(v_tExprType(i) IN (EXPR_LITERAL, EXPR_PSNODE))THEN
3993
3994 lhsName := GENERATE_NUMERIC_PART(i, v_NodeId);
3995 v_NodeId := v_tExprPsNodeId(i);
3996 rhsName := GENERATE_NUMERIC_PART(rhsNode, v_NodeId);
3997
3998 GENERATE_CONTRIBUTE_RECORD;
3999 nSuffix := nSuffix + 1;
4000 ELSE
4001
4002 RAISE CZ_R_INVALID_NUMRULE_NODE;
4003 END IF;
4004 END LOOP;
4005 END;
4006 ---------------------------------------------------------------------------------------
4007 PROCEDURE GENERATE_DYNAMIC_LOGIC IS
4008 v_result tStringArray;
4009 v_children tIntegerArray;
4010 ListType PLS_INTEGER;
4011 v_name VARCHAR2(4000);
4012 v_return VARCHAR2(4000);
4013 v_object VARCHAR2(4000);
4014 v_index PLS_INTEGER;
4015 BEGIN
4016
4017 IF(v_tExprType(jConsequentRoot) = EXPR_ARGUMENT)THEN
4018
4019 ListType := DATA_TYPE_NODE;
4020 v_result := GENERATE_ARGUMENT(jConsequentRoot, ListType);
4021 END IF;
4022
4023 nLocalDefaults := nLocalDefaults + 1;
4024 v_return := t_prefix || TO_CHAR(nLocalDefaults);
4025 v_index := 1;
4026
4027 v_result.DELETE;
4028 v_result := GENERATE_EXPRESSION(jAntecedentRoot, ListType);
4029 v_children := EXPAND_NODE_OPTIONAL(v_tExprPsNodeId(jConsequentRoot));
4030
4031 FOR i IN 1..v_result.COUNT LOOP
4032 FOR ii IN 1..v_children.COUNT LOOP
4033
4034 v_name := GENERATE_NAME_EXPL(v_tExplNodeId(jConsequentRoot), glPsNodeId(v_children(ii)));
4035 v_object := v_return || '_' || TO_CHAR(v_index);
4036
4037 vLogicLine := 'OBJECT ' || v_object || NewLine ||
4038 'GS I ... ' || TO_CHAR(nReasonId) || NewLine ||
4039 'GL' || OperatorLetters(OPERATOR_ALLOF) || v_name || NewLine ||
4040 'GR' || OperatorLetters(OPERATOR_ALLOF) || v_object || NewLine ||
4041 'INC ' || v_result(i) || ' ' || v_object || ' ' || v_name ||
4042 ' ... ' || TO_CHAR(nReasonId) || NewLine;
4043 PACK;
4044
4045 v_index := v_index + 1;
4046 END LOOP;
4047 END LOOP;
4048 END GENERATE_DYNAMIC_LOGIC;
4049 ---------------------------------------------------------------------------------------
4050 PROCEDURE GENERATE_NUMERIC_RULE IS
4051
4052 v_index PLS_INTEGER;
4053 BEGIN
4054
4055 IF(jAntecedentRoot IS NULL OR jConsequentRoot IS NULL)THEN
4056 RAISE CZ_R_INVALID_NUMERIC_RULE;
4057 END IF;
4058
4059 IF(v_tExprType(jAntecedentRoot) = EXPR_OPERATOR AND (NOT v_ChildrenIndex.EXISTS(v_tExprId(jAntecedentRoot))))THEN
4060 RAISE CZ_R_INCOMPLETE_NUMERIC_RULE;
4061 END IF;
4062
4063 IF(HAS_INTEGER_VALUE(jConsequentRoot) = GENERATE_INCREMENT)THEN
4064
4065 --For a numeric rule, if RHS has an integer value, the antecedent root should be a rounding operator.
4066 --As a fix for the bug #3558699, we are making this check more flexible - we require the rounding
4067 --operator only if the data type of the antecedent is not convertible to integer.
4068 --As a fix for the bug #3764347, if the antecedent root is a multiply operator, we drill down into
4069 --its operands and check their data types.
4070
4071 IF(v_tExprType(jAntecedentRoot) <> EXPR_OPERATOR OR v_tExprSubtype(jAntecedentRoot) NOT IN
4072 (OPERATOR_ROUND, OPERATOR_CEILING, OPERATOR_FLOOR, OPERATOR_TRUNCATE))THEN
4073
4074 v_index := jAntecedentRoot;
4075 IF(v_tExprType(v_index) = EXPR_OPERATOR AND v_tExprSubtype(v_index) = OPERATOR_NONE)THEN
4076
4077 --Bug #4180719. This is an empty operator, drill down one level.
4078
4079 v_index:= v_ChildrenIndex(v_tExprId(v_index));
4080 END IF;
4081
4082 IF(v_tExprType(v_index) = EXPR_OPERATOR AND v_tExprSubtype(v_index) = OPERATOR_MULT)THEN
4083
4084 --This is a multiply operator, check the data types of the children.
4085
4086 v_index := v_ChildrenIndex(v_tExprId(v_index));
4087
4088 IF((NOT COMPATIBLE_DATA_TYPES(v_tExprDataType(v_index), DATA_TYPE_INTEGER)) OR
4089 (NOT COMPATIBLE_DATA_TYPES(v_tExprDataType(v_index + 1), DATA_TYPE_INTEGER)))THEN
4090
4091 RAISE CZ_R_INVALID_NUM_SIMPLE_EXPR;
4092 END IF;
4093 ELSIF(NOT COMPATIBLE_DATA_TYPES(v_tExprDataType(v_index), DATA_TYPE_INTEGER))THEN
4094
4095 RAISE CZ_R_INVALID_NUM_SIMPLE_EXPR;
4096 END IF;
4097 END IF;
4098
4099 GENERATE_INCREMENT_LOGIC;
4100 ELSIF(HAS_INTEGER_VALUE(jConsequentRoot) = GENERATE_CONTRIBUTE)THEN
4101 GENERATE_CONTRIBUTE_LOGIC;
4102 ELSIF(HAS_INTEGER_VALUE(jConsequentRoot) = GENERATE_DYNAMIC)THEN
4103 GENERATE_DYNAMIC_LOGIC;
4104 ELSE
4105 RAISE CZ_R_PARAMETER_NOT_FOUND;
4106 END IF;
4107 END;
4108 ---------------------------------------------------------------------------------------
4109 PROCEDURE GENERATE_COMPARISON_RULE IS
4110 leftOper tStringArray;
4111 rightOper tStringArray;
4112 ListType PLS_INTEGER;
4113 jRoot PLS_INTEGER;
4114 jChild PLS_INTEGER;
4115 BEGIN
4116
4117 IF(jAntecedentRoot IS NULL OR jConsequentRoot IS NULL)THEN
4118 RAISE CZ_R_INVALID_COMPARISON_RULE;
4119 END IF;
4120
4121 leftOper := GENERATE_EXPRESSION(jAntecedentRoot, ListType);
4122
4123 jRoot := jConsequentRoot;
4124
4125 IF(v_tExprType(jRoot) = EXPR_OPERATOR AND v_tExprSubtype(jRoot) IN (OPERATOR_ALLOF, OPERATOR_ANYOF) AND
4126 v_NumberOfChildren(v_tExprId(jRoot)) = 1)THEN
4127
4128 jChild := v_ChildrenIndex(v_tExprId(jRoot));
4129 IF(v_tExprType(jChild) = EXPR_PSNODE AND (NOT v_ChildrenIndex.EXISTS(v_tExprId(jChild))))THEN
4130
4131 jRoot := jChild;
4132 END IF;
4133 END IF;
4134
4135 rightOper := GENERATE_EXPRESSION(jRoot, ListType);
4136
4137 vLogicLine := 'GS' || OperatorLetters(nRuleOperator) || '... ' || TO_CHAR(nReasonId) || NewLine ||
4138 'GL' || OperatorLetters(OPERATOR_ALLOF) || leftOper(1) || NewLine ||
4139 'GR' || OperatorLetters(OPERATOR_ALLOF) || rightOper(1) || NewLine;
4140
4141 PACK;
4142 END;
4143 ---------------------------------------------------------------------------------------
4144 FUNCTION GENERATE_LOGIC_TREE(j IN PLS_INTEGER) RETURN tStringArray IS
4145 v_return tStringArray;
4146 BEGIN
4147
4148 IF((NOT v_ChildrenIndex.EXISTS(v_tExprId(j))) OR v_NumberOfChildren(v_tExprId(j)) <> 2)THEN
4149 RAISE CZ_R_INVALID_LOGIC_RULE;
4150 END IF;
4151
4152 nRuleOperator := v_tExprSubtype(j);
4153 jAntecedentRoot := v_ChildrenIndex(v_tExprId(j));
4154 jConsequentRoot := jAntecedentRoot + 1;
4155
4156 v_tExprParentId(jAntecedentRoot) := NULL;
4157 v_tExprParentId(jConsequentRoot) := NULL;
4158
4159 --High-level logic rule validation section. Should not do these validations for comparison rules.
4160 --Make sure antecedent and consequent nodes have logical value.
4161 --If this is a comparison rule with a DEFAULT operator, which was not allowed before, we will
4162 --generate this rule as a logic rule (bug #3343569).
4163
4164 IF(RuleTemplateType = RULE_TYPE_LOGIC_RULE OR nPresentationFlag = FLAG_FREEFORM_RULE OR
4165 nRuleOperator = RULE_OPERATOR_DEFAULTS)THEN
4166
4167 nRuleType := RULE_TYPE_LOGIC_RULE;
4168
4169 IF(NOT HAS_LOGICAL_VALUE(jAntecedentRoot))THEN
4170 nParam := jAntecedentRoot;
4171 IF(v_tExprPsNodeId(nParam) IS NULL)THEN
4172 localString := NULL;
4173 ELSE
4174 localString := glName(glIndexByPsNodeId(v_tExprPsNodeId(nParam)));
4175 END IF;
4176
4177 RAISE CZ_R_LOGIC_RULE_WRONG_FEAT;
4178 END IF;
4179
4180 IF(NOT HAS_LOGICAL_VALUE(jConsequentRoot))THEN
4181 nParam := jConsequentRoot;
4182 IF(v_tExprPsNodeId(nParam) IS NULL)THEN
4183 localString := NULL;
4184 ELSE
4185 localString := glName(glIndexByPsNodeId(v_tExprPsNodeId(nParam)));
4186 END IF;
4187
4188 RAISE CZ_R_LOGIC_RULE_WRONG_FEAT;
4189 END IF;
4190
4191 GENERATE_LOGIC_RULE;
4192
4193 ELSIF(RuleTemplateType = RULE_TYPE_COMPARISON_RULE)THEN
4194
4195 nRuleType := RULE_TYPE_COMPARISON_RULE;
4196 GENERATE_COMPARISON_RULE;
4197
4198 ELSE
4199
4200 RAISE CZ_R_UNKNOWN_RULE_TYPE;
4201 END IF;
4202 RETURN v_return;
4203 END;
4204 ---------------------------------------------------------------------------------------
4205 FUNCTION GENERATE_NUMERIC_TREE(j IN PLS_INTEGER) RETURN tStringArray IS
4206 v_return tStringArray;
4207 BEGIN
4208
4209 IF((NOT v_ChildrenIndex.EXISTS(v_tExprId(j))) OR v_NumberOfChildren(v_tExprId(j)) <> 2)THEN
4210 RAISE CZ_R_INVALID_NUMERIC_RULE;
4211 END IF;
4212
4213 nRuleType := RULE_TYPE_NUMERIC_RULE;
4214
4215 nRuleOperator := v_tExprSubtype(j);
4216 jAntecedentRoot := v_ChildrenIndex(v_tExprId(j));
4217 jConsequentRoot := jAntecedentRoot + 1;
4218
4219 v_tExprParentId(jAntecedentRoot) := NULL;
4220 v_tExprParentId(jConsequentRoot) := NULL;
4221
4222 --High-level numeric rule validation section.
4223 --Make sure participating features have correct types.
4224
4225 FOR i IN expressionStart..expressionEnd LOOP
4226 IF(v_tExprPsNodeId(i) IS NOT NULL)THEN
4227
4228 localMinimum := glIndexByPsNodeId(v_tExprPsNodeId(i));
4229
4230 IF(glPsNodeType(localMinimum) = PS_NODE_TYPE_FEATURE AND
4231 glFeatureType(localMinimum) = PS_NODE_FEATURE_TYPE_STRING)THEN
4232
4233 nParam := i;
4234 RAISE CZ_R_NUMERIC_RULE_WRONG_FEAT;
4235 END IF;
4236
4237 IF(i = jConsequentRoot AND trackableAncestor.EXISTS(v_tExprPsNodeId(i)))THEN
4238
4239 --This node is an ancestor of a BOM trackable item. It should be prohibited from
4240 --participating on the RHS of a numeric rule.
4241
4242 nParam := glIndexByPsNodeId(v_tExprPsNodeId(i));
4243 RAISE CZ_R_TRACKABLE_ANCESTOR;
4244 END IF;
4245 END IF;
4246 END LOOP;
4247
4248 GENERATE_NUMERIC_RULE;
4249 RETURN v_return;
4250 END;
4251 ---------------------------------------------------------------------------------------
4252 FUNCTION GENERATE_TEMPLATE_APPLICATION(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER)
4253 RETURN tStringArray IS
4254
4255 v_return tStringArray;
4256 h_mapExprId tIntegerArray_idx_vc2;
4257
4258 jdef PLS_INTEGER;
4259 templateStart PLS_INTEGER;
4260 templateEnd PLS_INTEGER;
4261 v_index PLS_INTEGER;
4262
4263 ---------------------------------------------------------------------------------------
4264 PROCEDURE READ_TEMPLATE(p_template_id IN NUMBER) IS
4265
4266 --These are local arrays used only to transfer data to the relevant expression arrays.
4267
4268 v_NodeId tExplNodeId;
4269 v_Type tExprType;
4270 v_Subtype tExprSubtype;
4271 v_Id tExprId;
4272 v_ParentId tExprParentId;
4273 v_TemplateId tExprTemplateId;
4274 v_ExpressId tExpressId;
4275 v_PsNodeId tExplNodeId;
4276 v_DataValue tExprDataValue;
4277 v_PropertyId tExprPropertyId;
4278 v_ArgumentIndex tExprArgumentIndex;
4279 v_ArgumentName tExprArgumentName;
4280 v_ConsequentFlag tConsequentFlag;
4281 v_DataNumValue tExprDataNumValue;
4282 v_DataType tExprDataType;
4283
4284 BEGIN
4285
4286 nDebug := 8010100;
4287
4288 IF(NOT memoryTemplateStart.EXISTS(p_template_id))THEN
4289
4290 SELECT model_ref_expl_id, expr_type, expr_node_id, expr_parent_id, template_id,
4291 express_id, expr_subtype, ps_node_id, data_value, property_id, argument_index,
4292 argument_name, consequent_flag, data_num_value, data_type
4293 BULK COLLECT INTO v_NodeId, v_Type, v_Id, v_ParentId, v_TemplateId,
4294 v_ExpressId, v_Subtype, v_PsNodeId, v_DataValue, v_PropertyId, v_ArgumentIndex,
4295 v_ArgumentName, v_ConsequentFlag, v_DataNumValue, v_DataType
4296 FROM cz_expression_nodes
4297 WHERE rule_id = p_template_id
4298 AND expr_type <> EXPR_NODE_TYPE_PUNCT
4299 AND deleted_flag = FLAG_NOT_DELETED
4300 ORDER BY expr_parent_id, seq_nbr;
4301
4302 nDebug := 8010101;
4303
4304 IF(v_Id.COUNT = 0)THEN
4305 RAISE CZ_R_TEMPLATE_UNKNOWN;
4306 END IF;
4307
4308 v_index := v_tTmplId.COUNT + 1;
4309 memoryTemplateStart(p_template_id) := v_index;
4310
4311 nDebug := 8010102;
4312
4313 FOR i IN 1..v_Id.COUNT LOOP
4314
4315 IF(v_DataNumValue(i) IS NOT NULL)THEN v_DataValue(i) := TO_CHAR(v_DataNumValue(i)); END IF;
4316
4317 v_tTmplNodeId(v_index) := v_NodeId(i);
4318 v_tTmplType(v_index) := v_Type(i);
4319 v_tTmplSubtype(v_index) := v_Subtype(i);
4320 v_tTmplId(v_index) := v_Id(i);
4321 v_tTmplParentId(v_index) := v_ParentId(i);
4322 v_tTmplTemplateId(v_index) := v_TemplateId(i);
4323 v_tTmplExpressId(v_index) := v_ExpressId(i);
4324 v_tTmplPsNodeId(v_index) := v_PsNodeId(i);
4325 v_tTmplPropertyId(v_index) := v_PropertyId(i);
4326 v_tTmplArgumentIndex(v_index) := v_ArgumentIndex(i);
4327 v_tTmplArgumentName(v_index) := v_ArgumentName(i);
4328 v_tTmplConsequent(v_index) := v_ConsequentFlag(i);
4329 v_tTmplDataValue(v_index) := v_DataValue(i);
4330 v_tTmplDataType(v_index) := v_DataType(i);
4331
4332 v_index := v_index + 1;
4333 END LOOP;
4334
4335 memoryTemplateEnd(p_template_id) := v_tTmplId.COUNT;
4336 END IF;
4337 END;
4338 ---------------------------------------------------------------------------------------
4339 FUNCTION COPY_EXPRESSION_NODE(j_from IN PLS_INTEGER, j_parent IN PLS_INTEGER)
4340 RETURN PLS_INTEGER IS
4341 j_to PLS_INTEGER;
4342 BEGIN
4343
4344 nDebug := 8010105;
4345
4346 j_to := v_tExprId.COUNT + 1;
4347 nLocalExprId := nLocalExprId + 1;
4348
4349 v_tExprId(j_to) := nLocalExprId;
4350 v_tExprParentId(j_to) := j_parent;
4351
4352 v_tExplNodeId(j_to) := v_tExplNodeId(j_from);
4353 v_tExprType(j_to) := v_tExprType(j_from);
4354 v_tExprSubtype(j_to) := v_tExprSubtype(j_from);
4355 v_tExprTemplateId(j_to) := v_tExprTemplateId(j_from);
4356 v_tExprParamIndex(j_to) := v_tExprParamIndex(j_from);
4357 v_tExprParSignature(j_to) := v_tExprParSignature(j_from);
4358 v_tExpressId(j_to) := v_tExpressId(j_from);
4359 v_tExprPsNodeId(j_to) := v_tExprPsNodeId(j_from);
4360 v_tExprDataValue(j_to) := v_tExprDataValue(j_from);
4361 v_tExprDataType(j_to) := v_tExprDataType(j_from);
4362 v_tExprPropertyId(j_to) := v_tExprPropertyId(j_from);
4363 v_tConsequentFlag(j_to) := v_tConsequentFlag(j_from);
4364 v_tExprArgumentName(j_to) := v_tExprArgumentName(j_from);
4365
4366 nDebug := 8010106;
4367
4368 RETURN j_to;
4369 END;
4370 ---------------------------------------------------------------------------------------
4371 PROCEDURE COPY_EXPRESSION_TREE(j_from IN PLS_INTEGER, j_parent IN PLS_INTEGER) IS
4372 j_child PLS_INTEGER;
4373 j_children tIntegerArray;
4374 BEGIN
4375
4376 nDebug := 8010107;
4377
4378 IF(v_ChildrenIndex.EXISTS(v_tExprId(j_from)))THEN
4379
4380 j_child := v_ChildrenIndex(v_tExprId(j_from));
4381
4382 WHILE(v_tExprParentId(j_child) = v_tExprId(j_from))LOOP
4383
4384 j_children(j_child) := COPY_EXPRESSION_NODE(j_child, j_parent);
4385 j_child := j_child + 1;
4386 END LOOP;
4387
4388 j_child := v_ChildrenIndex(v_tExprId(j_from));
4389
4390 WHILE(v_tExprParentId(j_child) = v_tExprId(j_from))LOOP
4391
4392 COPY_EXPRESSION_TREE(j_child, j_children(j_child));
4393 j_child := j_child + 1;
4394 END LOOP;
4395 END IF;
4396
4397 nDebug := 8010108;
4398
4399 END;
4400 ---------------------------------------------------------------------------------------
4401 BEGIN
4402
4403 RuleTemplateType := v_tExprSubtype(j);
4404 READ_TEMPLATE(RuleTemplateType);
4405 templateStart := v_tExprId.COUNT + 1;
4406
4407 FOR i IN memoryTemplateStart(RuleTemplateType)..memoryTemplateEnd(RuleTemplateType) LOOP
4408
4409 IF(v_tTmplType(i) = EXPR_ARGUMENT AND v_tTmplArgumentIndex(i) IS NOT NULL)THEN
4410
4411 nDebug := 8010109;
4412
4413 --This is an argument, may correspond to a collection of paramaters in the template
4414 --application.
4415
4416 jdef := 0;
4417
4418 FOR ii IN expressionStart..expressionEnd LOOP
4419
4420 IF(v_tExprParamIndex(ii) = v_tTmplArgumentIndex(i))THEN
4421
4422 jdef := 1;
4423 v_index := v_tExprId.COUNT + 1;
4424 nLocalExprId := nLocalExprId + 1;
4425
4426 v_tExprId(v_index) := nLocalExprId;
4427 h_mapExprId(v_tExprId(ii)) := nLocalExprId;
4428
4429 --If this entry gets overwritten many times, it is not a problem because in this case it
4430 --will never be used.
4431
4432 h_mapExprId(v_tTmplId(i)) := nLocalExprId;
4433
4434 v_tExprParentId(v_index) := v_tTmplParentId(i);
4435 v_tExplNodeId(v_index) := v_tExplNodeId(ii);
4436 v_tExprType(v_index) := v_tExprType(ii);
4437 v_tExprSubtype(v_index) := v_tExprSubtype(ii);
4438 v_tExprTemplateId(v_index) := v_tExprTemplateId(ii);
4439 v_tExpressId(v_index) := v_tExpressId(ii);
4440 v_tExprPsNodeId(v_index) := v_tExprPsNodeId(ii);
4441 v_tExprDataValue(v_index) := v_tExprDataValue(ii);
4442 v_tExprDataType(v_index) := v_tExprDataType(ii);
4443 v_tExprPropertyId(v_index) := v_tExprPropertyId(ii);
4444 v_tConsequentFlag(v_index) := v_tConsequentFlag(ii);
4445 v_tExprArgumentName(v_index) := v_tExprArgumentName(ii);
4446 v_tExprParamIndex(v_index) := v_tExprParamIndex(ii);
4447 v_tExprParSignature(v_index) := v_tExprParSignature(ii);
4448
4449 IF(v_tExprType(v_index) = EXPR_TEMPLATE)THEN v_tExprType(v_index) := EXPR_OPERATOR; END IF;
4450 END IF;
4451 END LOOP;
4452
4453 --No parameter was found for this argument - incomplete rule.
4454
4455 IF(jdef = 0)THEN RAISE CZ_R_INCORRECT_NODE_ID; END IF;
4456 ELSE
4457
4458 nDebug := 8010110;
4459
4460 --This is a regular node in the template definition, just copy.
4461
4462 v_index := v_tExprId.COUNT + 1;
4463 nLocalExprId := nLocalExprId + 1;
4464
4465 v_tExprId(v_index) := nLocalExprId;
4466 h_mapExprId(v_tTmplId(i)) := nLocalExprId;
4467
4468 v_tExprParentId(v_index) := v_tTmplParentId(i);
4469 v_tExplNodeId(v_index) := v_tTmplNodeId(i);
4470 v_tExprType(v_index) := v_tTmplType(i);
4471 v_tExprSubtype(v_index) := v_tTmplSubtype(i);
4472 v_tExprTemplateId(v_index) := v_tTmplTemplateId(i);
4473 v_tExpressId(v_index) := v_tTmplExpressId(i);
4474 v_tExprPsNodeId(v_index) := v_tTmplPsNodeId(i);
4475 v_tExprDataValue(v_index) := v_tTmplDataValue(i);
4476 v_tExprDataType(v_index) := v_tTmplDataType(i);
4477 v_tExprPropertyId(v_index) := v_tTmplPropertyId(i);
4478 v_tConsequentFlag(v_index) := v_tTmplConsequent(i);
4479 v_tExprArgumentName(v_index) := v_tTmplArgumentName(i);
4480 END IF;
4481 END LOOP;
4482
4483 nDebug := 8010111;
4484
4485 templateEnd := v_tExprId.COUNT;
4486
4487 FOR i IN templateStart..templateEnd LOOP
4488
4489 IF(v_tExprParentId(i) IS NOT NULL)THEN
4490
4491 IF(NOT h_mapExprId.EXISTS(v_tExprParentId(i)))THEN RAISE CZ_R_INCORRECT_NODE_ID; END IF;
4492 v_tExprParentId(i) := h_mapExprId(v_tExprParentId(i));
4493 END IF;
4494 END LOOP;
4495
4496 nDebug := 8010112;
4497
4498 FOR i IN expressionStart..expressionEnd LOOP
4499
4500 IF(h_mapExprId.EXISTS(v_tExprId(i)))THEN
4501
4502 COPY_EXPRESSION_TREE(i, h_mapExprId(v_tExprId(i)));
4503 END IF;
4504 END LOOP;
4505
4506 expressionStart := templateStart;
4507 expressionEnd := v_tExprId.COUNT;
4508
4509 nDebug := 8010114;
4510
4511 --We need to populate all the auxiliary arrays because now this is the expression we will be
4512 --processing. We don't really have to empty these arrays.
4513
4514 v_IndexByExprNodeId.DELETE;
4515 v_NumberOfChildren.DELETE;
4516 v_ChildrenIndex.DELETE;
4517
4518 FOR i IN expressionStart..expressionEnd LOOP
4519
4520 v_tExprSubtype(i) := v_tExprTemplateId(i);
4521
4522 --Add the indexing option.
4523
4524 v_IndexByExprNodeId(v_tExprId(i)) := i;
4525
4526 IF(v_tExprParentId(i) IS NOT NULL)THEN
4527
4528 IF(v_NumberOfChildren.EXISTS(v_tExprParentId(i)))THEN
4529 v_NumberOfChildren(v_tExprParentId(i)) := v_NumberOfChildren(v_tExprParentId(i)) + 1;
4530 ELSE
4531 v_NumberOfChildren(v_tExprParentId(i)) := 1;
4532 END IF;
4533
4534 IF(NOT v_ChildrenIndex.EXISTS(v_tExprParentId(i)))THEN
4535 v_ChildrenIndex(v_tExprParentId(i)) := i;
4536 END IF;
4537
4538 ELSE
4539
4540 --This is the root of the exploded template application expression tree.
4541
4542 jdef := i;
4543 END IF;
4544
4545 nDebug := 8010115;
4546
4547 END LOOP;
4548
4549 nDebug := 8010116;
4550
4551 v_return := GENERATE_EXPRESSION(jdef, ListType);
4552 RETURN v_return;
4553 END;
4554 ---------------------------------------------------------------------------------------
4555 FUNCTION LOOKUP_ARGUMENT(j IN PLS_INTEGER) RETURN PLS_INTEGER IS
4556 argIndex PLS_INTEGER := 0;
4557 BEGIN
4558
4559 IF(parameterScope.COUNT = 0)THEN
4560 RAISE CZ_R_EMPTY_PARAMETER_SCOPE;
4561 END IF;
4562
4563 FOR i IN 1..parameterName.COUNT LOOP
4564 IF(parameterName(i) = v_tExprArgumentName(j))THEN argIndex := i; EXIT; END IF;
4565 END LOOP;
4566
4567 IF(argIndex = 0)THEN
4568 RAISE CZ_R_PARAMETER_NOT_FOUND;
4569 END IF;
4570
4571 RETURN argIndex;
4572 END;
4573 ---------------------------------------------------------------------------------------
4574 FUNCTION GENERATE_ARGUMENT(j IN PLS_INTEGER, ListType IN OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
4575 v_return tStringArray;
4576 argIndex PLS_INTEGER := 0;
4577 BEGIN
4578
4579 nDebug := 7004010;
4580
4581 --The procedure can be called with a particular ListType to get a specific field from the
4582 --parameter scope.
4583 --Call with ListType = 0 to get the data type from cz_expression_nodes.
4584 --When called with ListType NULL, generate name or return value field.
4585
4586 --Bug #4681261 - with re-using of temporary tables, we cannot use stored generated names
4587 --anymore because these names depend not only on ps_node_id, model_ref_expl_id but also
4588 --on where the rule is assined. Therefore need to generate the name here instead of in
4589 --generate_iterator.
4590
4591 argIndex := LOOKUP_ARGUMENT(j);
4592
4593 v_tExprPsNodeId(j) := parameterScope(argIndex).node_id;
4594 v_tExplNodeId(j) := parameterScope(argIndex).node_id_ex;
4595
4596 --If this is a node, generate name here.
4597
4598 IF(v_tExprPsNodeId(j) IS NOT NULL AND v_tExplNodeId(j) IS NOT NULL AND
4599 parameterScope(argIndex).node_value IS NULL AND parameterScope(argIndex).node_obj IS NULL)THEN
4600
4601 v_return(1) := GENERATE_NAME_EXPL(v_tExplNodeId(j), v_tExprPsNodeId(j));
4602 parameterScope(argIndex).node_value := v_return(1);
4603 parameterScope(argIndex).node_obj := v_return(1);
4604 END IF;
4605
4606 IF(ListType = DATA_TYPE_VOID)THEN ListType := v_tExprDataType(j); END IF;
4607 IF(ListType IN (DATA_TYPE_INTEGER, DATA_TYPE_DECIMAL, DATA_TYPE_BOOLEAN, DATA_TYPE_TEXT))THEN
4608
4609 v_return(1) := parameterScope(argIndex).node_value;
4610 ELSIF(ListType = DATA_TYPE_NODE)THEN
4611
4612 v_return(1) := parameterScope(argIndex).node_id;
4613 ELSIF(ListType = DATA_TYPE_VARIANT)THEN
4614
4615 v_return(1) := parameterScope(argIndex).node_obj;
4616 ELSE
4617
4618 v_return(1) := parameterScope(argIndex).node_value;
4619 END IF;
4620
4621 nDebug := 7004019;
4622
4623 RETURN v_return;
4624 END;
4625 ---------------------------------------------------------------------------------------
4626 FUNCTION GENERATE_FORALL(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tIteratorArray;
4627 ---------------------------------------------------------------------------------------
4628 FUNCTION GENERATE_REFNODE(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
4629 v_children tIntegerArray;
4630 v_object VARCHAR2(128);
4631 nodeChild NUMBER;
4632 featChild NUMBER;
4633 featPsNodeId NUMBER; --kdande; Bug 6881902; 11-Mar-2008
4634 LocalType PLS_INTEGER;
4635 IsNumeric PLS_INTEGER;
4636 IsNotZero PLS_INTEGER;
4637 nCheck NUMBER;
4638 countTrue PLS_INTEGER := 0;
4639 countFalse PLS_INTEGER := 0;
4640 v_actual VARCHAR2(16) := ' ';
4641 v_return tStringArray;
4642 v_propval tStringArray;
4643 v_psnode tStringArray;
4644 CurrentId NUMBER;
4645 nodeId NUMBER; --jonatara:bug7041718
4646 v_sysprop PLS_INTEGER;
4647 v_mutable VARCHAR2(1);
4648 v_collection VARCHAR2(1);
4649 v_context PLS_INTEGER;
4650 BEGIN
4651
4652 nDebug := 7004070;
4653
4654 CurrentId := v_tExprId(j);
4655 nodeChild := v_ChildrenIndex(CurrentId);
4656 nLocalDefaults := nLocalDefaults + 1;
4657
4658 IF(v_tExprType(j) = EXPR_ARGUMENT)THEN
4659
4660 --This is an argument, we assume that it is of type 'node'.
4661
4662 LocalType := DATA_TYPE_NODE;
4663 v_return := GENERATE_ARGUMENT(j, LocalType);
4664
4665 ELSE
4666
4667 --It's not an argument, so it's a ps_node.
4668
4669 v_return(1) := TO_CHAR(v_tExprPsNodeId(j));
4670 END IF;
4671
4672 nodeId := v_return(1);
4673
4674 WHILE(v_tExprParentId.EXISTS(nodeChild) AND v_tExprParentId(nodeChild) = CurrentId)LOOP
4675 IF(v_tExplNodeId(nodeChild) IS NULL OR v_tExplNodeId(nodeChild) = -1 OR
4676
4677 --Bug #3821827, caused by a corruption, when the explosion_id value was neither NULL or -1,
4678 --but was just some incorrect value when it is expected to be NULL.
4679
4680 (NOT v_NodeLogicLevel.EXISTS(v_tExplNodeId(nodeChild))))THEN
4681
4682 v_tExplNodeId(nodeChild) := v_ExplByPsNodeId(nodeId);
4683 END IF;
4684
4685 IF(h_SeededName.EXISTS(v_tExprSubtype(nodeChild)) AND h_SeededName(v_tExprSubtype(nodeChild)) = RULE_SYS_PROP_SELECTION)THEN
4686
4687 featChild := v_ChildrenIndex(CurrentId);
4688 featPsNodeId := v_return(1);
4689 v_children := EXPAND_NODE_OPTIONAL(featPsNodeId);
4690 v_sysprop := nodeChild + 1;
4691 LocalType := DATA_TYPE_VOID;
4692 v_context := 1;
4693
4694 IF(v_tExprParentId.EXISTS(v_sysprop) AND v_tExprParentId(v_sysprop) = CurrentId)THEN
4695
4696 --The system property was explicitly specified.
4697
4698 nDebug := 7004073;
4699
4700 IF(v_tExprType(v_sysprop) = EXPR_NODE_TYPE_SYSPROP)THEN
4701 IF(NOT h_SeededName.EXISTS(v_tExprSubtype(v_sysprop)))THEN RAISE CZ_E_BAD_PROPERTY_TYPE; END IF;
4702
4703 IF(NOT APPLICABLE_SYS_PROP(j, glPsNodeId(v_children(1)), v_tExprSubtype(v_sysprop)))THEN
4704
4705 auxIndex := v_children(1);
4706 localString := h_ReportName(v_tExprSubtype(v_sysprop));
4707 RAISE CZ_R_INCOMPATIBLE_SYSPROP;
4708 END IF;
4709 END IF;
4710
4711 v_tExplNodeId(v_sysprop) := v_ExplByPsNodeId(nodeId);
4712 v_context := 0;
4713 ELSE
4714
4715 --This is Node.Selection(), the actual system property is not specified. It can be either .State()
4716 --or .Quantity() depending on the context.
4717
4718 IF(COMPATIBLE_DATA_TYPES(GET_ARGUMENT_INFO(v_tExprParamIndex(j), v_tExprParSignature(j),
4719 v_mutable, v_collection), DATA_TYPE_BOOLEAN))THEN
4720 --The context is boolean.
4721
4722 nDebug := 7004071;
4723
4724 IF(NOT APPLICABLE_SYS_PROP(j, NULL, RULE_SYS_PROP_STATE))THEN
4725
4726 auxIndex := glIndexByPsNodeId(nodeId);
4727 localString := 'State';
4728 RAISE CZ_R_INCOMPATIBLE_SYSPROP;
4729 END IF;
4730
4731 ListType := DATA_TYPE_BOOLEAN;
4732 v_return.DELETE;
4733 v_return(1) := GENERATE_NAME(j, nodeId);
4734
4735 --This is Feature.Selection().State(), which in a boolean context is equivalent to Feature.
4736
4737 EXIT;
4738 ELSE
4739
4740 --The context is numeric.
4741
4742 nDebug := 7004072;
4743
4744 IF(NOT APPLICABLE_SYS_PROP(j, glPsNodeId(v_children(1)), RULE_SYS_PROP_QUANTITY))THEN
4745
4746 auxIndex := v_children(1);
4747 localString := 'Quantity';
4748 RAISE CZ_R_INCOMPATIBLE_SYSPROP;
4749 END IF;
4750
4751 LocalType := DATA_TYPE_DECIMAL;
4752 END IF;
4753 END IF;
4754
4755 v_return.DELETE;
4756
4757 IF(nRuleType = RULE_TYPE_NUMERIC_RULE AND v_context = 0 AND
4758 v_tExprType(v_sysprop) = EXPR_NODE_TYPE_SYSPROP AND
4759 h_SeededName(v_tExprSubtype(v_sysprop)) = RULE_SYS_PROP_STATE)THEN
4760
4761 --This is Node.Selection().State() in a numeric rule, State() was explicitly specified.
4762 --Bugs #4198455, #4366598.
4763
4764 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
4765 vLogicLine := 'OBJECT ' || v_return(1) || NewLine;
4766 PACK;
4767
4768 FOR i IN 1..v_children.COUNT LOOP
4769
4770 vLogicLine := 'OBJECT ' || v_return(1) || '_' || TO_CHAR(i) || NewLine ||
4771 'GS I ... ' || TO_CHAR(nReasonId) || NewLine ||
4772 'GL' || OperatorLetters(OPERATOR_ANYOF) || GENERATE_NAME(j, glPsNodeId(v_children(i))) || NewLine ||
4773 'GR' || OperatorLetters(OPERATOR_ANYOF) || v_return(1) || '_' || TO_CHAR(i) || NewLine;
4774 PACK;
4775
4776 vLogicLine := 'INC ' || v_return(1) || '_' || TO_CHAR(i) || ' ' || v_return(1) ||
4777 OperatorLiterals(OPERATOR_ROUND) || '... ' || TO_CHAR(nReasonId) || NewLine;
4778 PACK;
4779 END LOOP;
4780
4781 RETURN v_return;
4782 END IF;
4783
4784 FOR i IN 1..v_children.COUNT LOOP
4785
4786 v_propval(1) := TO_CHAR(glPsNodeId(v_children(i)));
4787
4788 IF(v_context = 1)THEN v_propval(1) := GENERATE_NAME(j, glPsNodeId(v_children(i)));
4789 ELSE v_propval := SYSTEM_PROPERTY_VALUE(v_sysprop, v_propval, LocalType); END IF;
4790 ListType := LocalType;
4791
4792 BEGIN
4793 nCheck := TO_NUMBER(v_propval(1));
4794 IsNumeric := 1;
4795 IsNotZero := 1;
4796 IF(nCheck = 0)THEN
4797 IsNotZero := 0;
4798 END IF;
4799 EXCEPTION
4800 WHEN OTHERS THEN
4801 IsNumeric := 0;
4802 IsNotZero := 1;
4803 END;
4804
4805 IF(LocalType IN (DATA_TYPE_INTEGER, DATA_TYPE_DECIMAL))THEN
4806
4807 v_object := t_prefix || TO_CHAR(nLocalDefaults) || '_' || TO_CHAR(i);
4808
4809 IF(IsNumeric = 1)THEN
4810
4811 --If a number, we have to GATE it throught the real option. We will do
4812 --it even if the property value is 0 for consistency.
4813
4814 vLogicLine := 'OBJECT ' || v_object || NewLine ||
4815 'GS I ... ' || TO_CHAR(nReasonId) || NewLine ||
4816 'GL' || OperatorLetters(OPERATOR_ANYOF) || GENERATE_NAME(featChild, glPsNodeId(v_children(i))) || NewLine ||
4817 'GR' || OperatorLetters(OPERATOR_ANYOF) || v_object || NewLine;
4818 ELSE
4819
4820 --If the property value is not numeric, then it is a "P_" name returned
4821 --as a result of Feat.#Selection.Count. In this case we have to GATE it
4822 --by making an INC from the real option. This prevents from propagating
4823 --when the option is FALSE.
4824
4825 vLogicLine := 'OBJECT ' || v_object || NewLine ||
4826 'INC ' || GENERATE_NAME(featChild, glPsNodeId(v_children(i))) || ' ' || v_object ||
4827 OperatorLiterals(OPERATOR_NONE) ||
4828 '... ' || TO_CHAR(nReasonId) || NewLine;
4829 END IF;
4830
4831 PACK;
4832
4833 IF(NOT v_return.EXISTS(1))THEN
4834
4835 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
4836 vLogicLine := 'TOTAL ' || v_return(1) || NewLine;
4837 PACK;
4838 END IF;
4839
4840 --In any case we multiply the property count (a number if it's .property or
4841 --the actual option if it is .#Count) by the intermediate object (the gate)
4842 --which is only true if the option is true. That way if no options selected
4843 --the result will be UNKNOWN.
4844
4845 IF(IsNumeric = 0)THEN
4846
4847 --If the property is not numeric then we multiply by 1 because it is the
4848 --count of the option.
4849
4850 vLogicLine := 'CONTRIBUTE ' || v_object || OperatorLiterals(OPERATOR_MULT) ||
4851 '1 ' || v_return(1) || v_actual || '... ' || TO_CHAR(nReasonId) || NewLine;
4852
4853 ELSIF(IsNotZero = 1)THEN
4854
4855 --If the property is not zero we have to multiply the gate by the property.
4856
4857 vLogicLine := 'CONTRIBUTE ' || v_object || OperatorLiterals(OPERATOR_MULT) ||
4858 v_propval(1) || ' ' || v_return(1) || v_actual || '... ' || TO_CHAR(nReasonId) || NewLine;
4859
4860 ELSE
4861
4862 --If the property value is 0, we will subtract the gate from the gate. This
4863 --is required in order to propagate 0 only if the option is selected. If we
4864 --used "gate * 0" it would always propagate 0, even if the gate is UNKNOWN,
4865 --and we don't want that to happen.
4866
4867 vLogicLine := 'CONTRIBUTE ' || v_object || OperatorLiterals(OPERATOR_SUB) ||
4868 v_object || ' ' || v_return(1) || v_actual || '... ' || TO_CHAR(nReasonId) || NewLine;
4869
4870 END IF;
4871 PACK;
4872
4873 ELSE
4874
4875 IF(LocalType <> DATA_TYPE_TEXT OR generateCompare = 1)THEN
4876
4877 v_return(i) := GENERATE_NAME(featChild, glPsNodeId(v_children(i))) || PROPERTY_DELIMITER || v_propval(1);
4878 ELSE
4879 --The expression contained a Text property which is only allowed in a comparison expression.
4880 --A Text property is not allowed in the context of your expression. Rule '%RULENAME' in
4881 --Model '%MODELNAME' ignored.
4882
4883 RAISE CZ_R_PROPERTY_NOT_ALLOWED;
4884 END IF;
4885 END IF;
4886 END LOOP;
4887
4888 IF(LocalType = DATA_TYPE_BOOLEAN)THEN
4889
4890 --The code inside this block has been changed as a fix for bug #1862896.
4891 --Start with creating gating objects and INC relations for all the extracted
4892 --options.
4893
4894 FOR i IN 1..v_return.COUNT LOOP
4895
4896 v_object := t_prefix || TO_CHAR(nLocalDefaults) || '_' || TO_CHAR(i);
4897 vLogicLine := 'OBJECT ' || v_object || NewLine ||
4898 'INC ' || EXTRACT_PROPERTY_NODE(v_return(i)) || ' ' || v_object ||
4899 OperatorLiterals(OPERATOR_ROUND) || '... ' || TO_CHAR(nReasonId) || NewLine;
4900
4901 --We are going to calculate the counts of true/false options in order to decide whether
4902 --we need to include the unsatisfied message id in the following GS relations. First we
4903 --overwrite the concatenated name/property value string in v_return to be just property
4904 --value as we don't use the concatenated format of v_return in this branch anymore.
4905
4906 v_return(i) := EXTRACT_PROPERTY_VALUE(v_return(i));
4907 IF(v_return(i) = BOOLEAN_TRUE_REPRESENTATION)THEN countTrue := countTrue + 1;
4908 ELSIF(v_return(i) = BOOLEAN_FALSE_REPRESENTATION)THEN countFalse := countFalse + 1;
4909 END IF;
4910
4911 PACK;
4912 END LOOP;
4913
4914 --This is the resulting object that will be returned. Any of the TRUE gating
4915 --objects requires this object, any of the FALSE gating objects negates it.
4916
4917 v_object := t_prefix || TO_CHAR(nLocalDefaults);
4918 vLogicLine := 'OBJECT ' || v_object || NewLine;
4919
4920 IF(countTrue > 0)THEN
4921
4922 localString := NULL;
4923 IF(countTrue > 1)THEN localString := sUnsatisfiedId; END IF;
4924
4925 vLogicLine := vLogicLine || 'GS R ' || localString || '... ' || TO_CHAR(nReasonId) || NewLine ||
4926 'GL' || OperatorLetters(OPERATOR_ANYOF);
4927 PACK;
4928
4929 nDebug := 8001156;
4930
4931 --Generate the list of all the TRUE gating objects.
4932
4933 FOR i IN 1..v_return.COUNT LOOP
4934
4935 IF(v_return(i) = BOOLEAN_TRUE_REPRESENTATION)THEN
4936 vLogicLine := v_object || '_' || TO_CHAR(i) || ' ';
4937 PACK;
4938 END IF;
4939 END LOOP;
4940
4941 vLogicLine := NewLine || 'GR' || OperatorLetters(OPERATOR_ANYOF) || v_object || NewLine;
4942 END IF;
4943
4944 IF(countFalse > 0)THEN
4945
4946 localString := NULL;
4947 IF(countFalse > 1)THEN localString := sUnsatisfiedId; END IF;
4948
4949 vLogicLine := vLogicLine || 'GS N ' || localString || '... ' || TO_CHAR(nReasonId) || NewLine ||
4950 'GL' || OperatorLetters(OPERATOR_ANYOF);
4951 PACK;
4952
4953 nDebug := 8001157;
4954
4955 --Generate the list of all the FALSE gating objects.
4956
4957 FOR i IN 1..v_return.COUNT LOOP
4958
4959 IF(v_return(i) = BOOLEAN_FALSE_REPRESENTATION)THEN
4960 vLogicLine := v_object || '_' || TO_CHAR(i) || ' ';
4961 PACK;
4962 END IF;
4963 END LOOP;
4964
4965 vLogicLine := NewLine || 'GR' || OperatorLetters(OPERATOR_ANYOF) || v_object || NewLine;
4966 END IF;
4967 PACK;
4968
4969 v_return.DELETE;
4970 v_return(1) := v_object;
4971
4972 END IF;
4973
4974 --We don't need to move on as we already processed the following expression node(s).
4975
4976 EXIT;
4977 ELSE
4978
4979 IF(v_tExprType(nodeChild) = EXPR_NODE_TYPE_SYSPROP)THEN
4980 IF(NOT h_SeededName.EXISTS(v_tExprSubtype(nodeChild)))THEN RAISE CZ_E_BAD_PROPERTY_TYPE; END IF;
4981
4982 IF(NOT APPLICABLE_SYS_PROP(j, NULL, v_tExprSubtype(nodeChild)))THEN
4983
4984 auxIndex := glIndexByPsNodeId(nodeId);
4985 localString := h_ReportName(v_tExprSubtype(nodeChild));
4986 RAISE CZ_R_INCOMPATIBLE_SYSPROP;
4987 END IF;
4988 END IF;
4989
4990 v_propval := SYSTEM_PROPERTY_VALUE(nodeChild, v_return, ListType);
4991
4992 IF(ListType = DATA_TYPE_TEXT)THEN
4993
4994 --This is a direct user or system property of DATA_TYPE_TEXT. Currently we don't allow
4995 --any operations to work with strings other than the comparison operators, therefore we
4996 --are going from here back to the GENERATE_COMPARE procedure , which expects the output
4997 --to be a combination of the node's P_ name and the property value.
4998
4999 --This whole IF block is a part of the fix for the bug #1706286.
5000
5001 IF(generateCompare = 1)THEN
5002
5003 FOR i IN 1..v_propval.COUNT LOOP
5004
5005 v_return(i) := GENERATE_NAME(v_ChildrenIndex(CurrentId), v_return(i)) || PROPERTY_DELIMITER || v_propval(i);
5006 END LOOP;
5007 ELSIF(generateCollect = 1)THEN
5008
5009 --Exclusion from the above comment: we can be generating the COLLECT expression. Such expression
5010 --can contain references to text properties to be used for comparison in the WHERE clause, but
5011 --at this time we do not know that they will be used in comparison. We need to just return the
5012 --value of the property.
5013
5014 v_return := v_propval;
5015 ELSE
5016 --The expression contained a Text property which is only allowed in a comparison expression.
5017 --A Text property is not allowed in the context of your expression. Rule '%RULENAME' in
5018 --Model '%MODELNAME' ignored.
5019
5020 RAISE CZ_R_PROPERTY_NOT_ALLOWED;
5021 END IF;
5022 ELSIF(ListType = DATA_TYPE_BOOLEAN AND v_tExprType(nodeChild) = EXPR_PROP)THEN
5023
5024 --For boolean user properties we replace the 0/1 values with corresponding object names.
5025 --Bug #3371279.
5026
5027 FOR i IN 1..v_propval.COUNT LOOP
5028 IF(v_propval(i) = BOOLEAN_TRUE_REPRESENTATION)THEN v_return(i) := ALWAYS_TRUE;
5029 ELSE v_return(i) := ALWAYS_FALSE; END IF;
5030 END LOOP;
5031 ELSE
5032
5033 v_return := v_propval;
5034 END IF;
5035 END IF;
5036
5037 nodeChild := nodeChild + 1;
5038 END LOOP;
5039
5040 nDebug := 7004080;
5041
5042 RETURN v_return;
5043 END;
5044 ---------------------------------------------------------------------------------------
5045 FUNCTION GENERATE_ITERATOR(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tIteratorArray IS
5046
5047 v_return tIteratorArray;
5048 v_iterin tIteratorArray;
5049 nChild PLS_INTEGER;
5050 nCount PLS_INTEGER;
5051 nGrand PLS_INTEGER;
5052 nType PLS_INTEGER;
5053 v_result tIntegerArray;
5054 v_record tStringArray;
5055 nodeName VARCHAR2(4000);
5056
5057 BEGIN
5058
5059 nDebug := 7004000;
5060
5061 nChild := v_ChildrenIndex(v_tExprId(j));
5062
5063 WHILE(v_tExprParentId(nChild) = v_tExprId(j))LOOP
5064
5065 v_result.DELETE;
5066 v_record.DELETE;
5067 v_iterin.DELETE;
5068
5069 nCount := v_return.COUNT + 1;
5070
5071 IF(v_tExprType(nChild) = EXPR_PSNODE)THEN
5072 IF(v_ChildrenIndex.EXISTS(v_tExprId(nChild)))THEN
5073 IF(HAS_OPTIONS_APPLIED(nChild))THEN
5074
5075 IF(v_NumberOfChildren(v_tExprId(j)) = 1)THEN
5076
5077 temp_table_hash_key(forallLevel) := TO_CHAR(v_tExprPsNodeId(nChild)) || '-' || TO_CHAR(v_tExplNodeId(nChild));
5078 temp_cmpt_hash_key(compatLevel) := temp_table_hash_key(forallLevel);
5079 END IF;
5080
5081 v_result := EXPAND_NODE(nChild);
5082
5083 FOR i IN 1..v_result.COUNT LOOP
5084
5085 --Bug #4681261 - with re-using of temporary tables, we cannot use stored generated names
5086 --anymore because these names depend not only on ps_node_id, model_ref_expl_id but also
5087 --on where the rule is assined. Name will be generated in generate_argument.
5088 --nodeName := GENERATE_NAME_EXPL(v_ExplByPsNodeId(v_result(i)), v_result(i));
5089
5090 v_return(nCount).node_type := DATA_TYPE_NODE;
5091 v_return(nCount).node_value := NULL;
5092 v_return(nCount).node_id := v_result(i);
5093 v_return(nCount).node_obj := NULL;
5094 v_return(nCount).node_id_ex := v_ExplByPsNodeId(v_result(i));
5095
5096 nCount := nCount + 1;
5097 END LOOP;
5098 ELSE
5099
5100 v_record := GENERATE_REFNODE(nChild, ListType);
5101
5102 FOR i IN 1..v_record.COUNT LOOP
5103
5104 v_return(nCount).node_type := ListType;
5105 v_return(nCount).node_value := v_record(i);
5106 v_return(nCount).node_id := NULL;
5107 v_return(nCount).node_obj := v_record(i);
5108
5109 nCount := nCount + 1;
5110 END LOOP;
5111 END IF;
5112 ELSE
5113
5114 --Bug #4681261 - with re-using of temporary tables, we cannot use stored generated names
5115 --anymore because these names depend not only on ps_node_id, model_ref_expl_id but also
5116 --on where the rule is assined. Name will be generated in generate_argument.
5117 --nodeName := GENERATE_NAME(nChild, v_tExprPsNodeId(nChild));
5118
5119 v_return(nCount).node_type := DATA_TYPE_NODE;
5120 v_return(nCount).node_value := NULL;
5121 v_return(nCount).node_id := v_tExprPsNodeId(nChild);
5122 v_return(nCount).node_obj := NULL;
5123 v_return(nCount).node_id_ex := v_tExplNodeId(nChild);
5124 END IF;
5125 ELSIF(v_tExprType(nChild) = EXPR_LITERAL)THEN
5126
5127 v_return(nCount).node_type := v_tExprDataType(nChild);
5128 v_return(nCount).node_value := v_tExprDataValue(nChild);
5129 v_return(nCount).node_id := NULL;
5130 v_return(nCount).node_obj := NULL;
5131
5132 ELSIF(v_tExprType(nChild) = EXPR_OPERATOR AND v_tExprSubtype(nChild) IN (OPERATOR_OPTIONSOF, OPERATOR_BOMOPTIONSOF))THEN
5133
5134 nGrand := v_ChildrenIndex(v_tExprId(nChild));
5135
5136 IF(v_NumberOfChildren(v_tExprId(j)) = 1)THEN
5137
5138 temp_table_hash_key(forallLevel) := TO_CHAR(v_tExprPsNodeId(nGrand)) || '-' || TO_CHAR(v_tExplNodeId(nGrand));
5139 temp_cmpt_hash_key(compatLevel) := temp_table_hash_key(forallLevel);
5140 END IF;
5141
5142 v_result := EXPAND_NODE(nChild);
5143
5144 FOR i IN 1..v_result.COUNT LOOP
5145
5146 --Bug #4681261 - with re-using of temporary tables, we cannot use stored generated names
5147 --anymore because these names depend not only on ps_node_id, model_ref_expl_id but also
5148 --on where the rule is assined. Name will be generated in generate_argument.
5149 --nodeName := GENERATE_NAME_EXPL(v_ExplByPsNodeId(v_result(i)), v_result(i));
5150
5151 v_return(nCount).node_type := DATA_TYPE_NODE;
5152 v_return(nCount).node_value := NULL;
5153 v_return(nCount).node_id := v_result(i);
5154 v_return(nCount).node_obj := NULL;
5155 v_return(nCount).node_id_ex := v_ExplByPsNodeId(v_result(i));
5156
5157 nCount := nCount + 1;
5158 END LOOP;
5159
5160 ELSIF(v_tExprType(nChild) IN (EXPR_FORALL, EXPR_FORALL_DISTINCT))THEN
5161
5162 v_iterin := GENERATE_FORALL(nChild, ListType);
5163
5164 FOR i IN 1..v_iterin.COUNT LOOP
5165
5166 v_return(nCount) := v_iterin(i);
5167 nCount := nCount + 1;
5168 END LOOP;
5169 ELSE
5170
5171 v_record := GENERATE_EXPRESSION(nChild, ListType);
5172
5173 IF(v_tExprPsNodeId(nChild) IS NOT NULL)THEN
5174
5175 nType := v_tExprType(nChild);
5176 v_tExprType(nChild) := EXPR_PSNODE;
5177
5178 v_iterin := GENERATE_ITERATOR(j, ListType);
5179 v_tExprType(nChild) := nType;
5180
5181 FOR i IN 1..v_iterin.COUNT LOOP
5182
5183 v_return(nCount) := v_iterin(i);
5184 nCount := nCount + 1;
5185 END LOOP;
5186
5187 ELSE
5188
5189 FOR i IN 1..v_record.COUNT LOOP
5190
5191 v_return(nCount).node_type := DATA_TYPE_VARIANT;
5192 v_return(nCount).node_value := v_record(i);
5193
5194 --If it's a 'P_' object, the node_id should still be populated, otherwise it will be impossible
5195 --to use properties of this objects.
5196
5197 v_return(nCount).node_id := NULL;
5198 v_return(nCount).node_obj := v_record(i);
5199
5200 nCount := nCount + 1;
5201 END LOOP;
5202 END IF;
5203 END IF;
5204
5205 nChild := nChild + 1;
5206 END LOOP;
5207
5208 nDebug := 7004009;
5209
5210 RETURN v_return;
5211 END;
5212 ---------------------------------------------------------------------------------------
5213 FUNCTION EXTRACT_PROPERTY_INFO(j IN PLS_INTEGER, PropName OUT NOCOPY VARCHAR2,
5214 DataType OUT NOCOPY PLS_INTEGER,
5215 PropertyType OUT NOCOPY PLS_INTEGER)
5216 RETURN PLS_INTEGER IS
5217 propChild PLS_INTEGER := v_ChildrenIndex(v_tExprId(j));
5218 propertyId PLS_INTEGER;
5219 tempVal NUMBER := -1;
5220 BEGIN
5221
5222 nDebug := 7004040;
5223
5224 PropertyType := 0;
5225
5226 WHILE(v_tExprParentId(propChild) = v_tExprId(j) AND
5227 v_tExprPropertyId(propChild) IS NULL AND v_tExprType(propChild) NOT IN
5228 (EXPR_NODE_TYPE_SYSPROP, EXPR_LITERAL))LOOP
5229 propChild := propChild + 1;
5230 END LOOP;
5231
5232 nDebug := 7004042;
5233
5234 IF(v_tExprParentId(propChild) = v_tExprId(j))THEN
5235 BEGIN
5236 IF(v_tExprPropertyId(propChild) IS NOT NULL)THEN
5237
5238 SELECT data_type, name INTO DataType, PropName
5239 FROM cz_properties
5240 WHERE deleted_flag = FLAG_NOT_DELETED
5241 AND property_id = v_tExprPropertyId(propChild);
5242 nDebug := 7004043;
5243
5244 RETURN v_tExprPropertyId(propChild);
5245
5246 ELSIF(v_tExprType(propChild) = EXPR_LITERAL)THEN
5247
5248 SELECT property_id, data_type, name INTO propertyId, DataType, PropName
5249 FROM cz_properties
5250 WHERE deleted_flag = FLAG_NOT_DELETED
5251 AND name = v_tExprDataValue(propChild);
5252
5253 RETURN propertyId;
5254 ELSE
5255
5256 PropertyType := 1;
5257 WHILE(v_tExprParentId(propChild) = v_tExprId(j) AND
5258 h_SeededName(v_tExprSubtype(propChild)) = RULE_SYS_PROP_PARENT)LOOP
5259
5260 propChild := propChild + 1;
5261 PropertyType := PropertyType + 1;
5262 END LOOP;
5263 IF(v_tExprParentId(propChild) = v_tExprId(j))THEN
5264
5265 SELECT data_type, name INTO DataType, PropName
5266 FROM cz_system_properties_v
5267 WHERE rule_id = v_tExprSubtype(propChild);
5268
5269 RETURN v_tExprSubtype(propChild);
5270 ELSE
5271 RAISE CZ_E_INCORRECT_PROPERTY;
5272 END IF;
5273 END IF;
5274 EXCEPTION
5275 WHEN OTHERS THEN
5276 RAISE CZ_E_INCORRECT_PROPERTY;
5277 END;
5278 ELSE
5279 RAISE CZ_E_INCORRECT_PROPERTY;
5280 END IF;
5281 nDebug := 7004049;
5282 END;
5283 ---------------------------------------------------------------------------------------
5284 FUNCTION GENERATE_FORALL_(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tIteratorArray IS
5285
5286 iteratorIndex tIntegerArray;
5287 iterator tIteratorArray;
5288 whereIndex PLS_INTEGER := 0;
5289 expressionIndex PLS_INTEGER := 0;
5290 nChild PLS_INTEGER;
5291 nCount PLS_INTEGER;
5292 v_property_id tIntegerArray;
5293 v_data_type tIntegerArray;
5294 v_prop_name tStringArray;
5295 v_return tIteratorArray;
5296 v_express tStringArray;
5297 SQLCreate VARCHAR2(8000);
5298 SQLInsert VARCHAR2(8000);
5299 SQLValues VARCHAR2(8000);
5300 SQLSelect VARCHAR2(8000);
5301 SQLFrom VARCHAR2(8000);
5302 SQLWhere VARCHAR2(8000) := NULL;
5303 tableName VARCHAR2(4000);
5304 tableAlias VARCHAR2(4000);
5305 nodeId NUMBER; --jonatara:bug7041718
5306 itemId PLS_INTEGER;
5307 propertyId PLS_INTEGER;
5308 c_values refCursor;
5309 v_cursor NUMBER;
5310 propertyVal VARCHAR2(4000);
5311 localNumber NUMBER;
5312 localString VARCHAR2(4000);
5313 bindValue tStringArray;
5314 v_flag tIntegerArray;
5315 v_stack_start PLS_INTEGER;
5316 v_stack_end PLS_INTEGER;
5317 v_value_exists PLS_INTEGER := 0;
5318
5319 bind_node_id DBMS_SQL.NUMBER_TABLE;
5320 bind_node_id_ex DBMS_SQL.NUMBER_TABLE;
5321 bind_node_type DBMS_SQL.NUMBER_TABLE;
5322 bind_node_value DBMS_SQL.VARCHAR2_TABLE;
5323 bind_node_obj DBMS_SQL.VARCHAR2_TABLE;
5324
5325 TYPE bind_value_table IS TABLE OF DBMS_SQL.VARCHAR2_TABLE INDEX BY BINARY_INTEGER;
5326 bind_values bind_value_table;
5327 arg_table_name temp_table_hash_type;
5328 hash_propval_key VARCHAR2(4000);
5329 ---------------------------------------------------------------------------------------
5330 PROCEDURE EXPLORE_WHERE(j IN PLS_INTEGER, v_argument IN VARCHAR2) IS
5331 nChild PLS_INTEGER;
5332 nCount PLS_INTEGER;
5333 propertyId PLS_INTEGER;
5334 dataType PLS_INTEGER;
5335 propType PLS_INTEGER;
5336 propName cz_properties.name%TYPE;
5337 BEGIN
5338
5339 nDebug := 7004020;
5340
5341 nChild := v_ChildrenIndex(v_tExprId(j));
5342
5343 WHILE(v_tExprParentId(nChild) = v_tExprId(j))LOOP
5344
5345 nCount := v_property_id.COUNT + 1;
5346
5347 IF(v_ChildrenIndex.EXISTS(v_tExprId(nChild)))THEN
5348 IF(v_tExprType(nChild) = EXPR_ARGUMENT AND v_tExprArgumentName(nChild) = v_argument)THEN
5349
5350 propertyId := EXTRACT_PROPERTY_INFO(nChild, propName, dataType, propType);
5351
5352 nDebug := 7004021;
5353
5354 IF(NOT v_flag.EXISTS(propertyId))THEN
5355
5356 v_property_id(nCount) := propertyId;
5357 v_data_type(nCount) := dataType;
5358 v_prop_name(nCount) := propName;
5359 v_flag(propertyId) := propType;
5360 END IF;
5361 ELSE
5362
5363 EXPLORE_WHERE(nChild, v_argument);
5364 END IF;
5365 END IF;
5366 nChild := nChild + 1;
5367 END LOOP;
5368
5369 nDebug := 7004029;
5370 END;
5371 ---------------------------------------------------------------------------------------
5372 --This function finds every reference to iterators in the FORALL WHERE clause, replaces
5373 --arguments with <table_alias>.value string and reference nodes with <table_alias>.i_<property_id>
5374 --string. It returns the generated SQL WHERE clause of the SELECT statement. All the literal
5375 --values are collected in an array for later binding.
5376
5377 FUNCTION EXAMINE_WHERE_CLAUSE(j IN PLS_INTEGER) RETURN VARCHAR2 IS
5378 argChild PLS_INTEGER;
5379 propType PLS_INTEGER;
5380 jChild PLS_INTEGER;
5381 isLocal PLS_INTEGER := 0;
5382 LocalType PLS_INTEGER := DATA_TYPE_VOID;
5383 propName cz_properties.name%TYPE;
5384 v_extern tStringArray;
5385 v_quotes VARCHAR2(2);
5386 BEGIN
5387
5388 nDebug := 7004030;
5389
5390 IF(v_tExprType(j) = EXPR_ARGUMENT)THEN
5391
5392 --This is an argument. First of all, find out if it corresponds to one of the local iterators - only
5393 --in this case there will be a temporary table with the corresponding name. Otherwise, it can be an
5394 --external argument from an upper level FORALL. In this case we have to get the value from the
5395 --parameter scope and use it as a literal in the generated WHERE clause.
5396
5397 FOR i IN 1..iteratorIndex.COUNT LOOP
5398
5399 IF(v_tExprArgumentName(iteratorIndex(i)) = v_tExprArgumentName(j))THEN isLocal := 1; END IF;
5400 END LOOP;
5401
5402 IF(isLocal = 1)THEN
5403
5404 --This is an argument that corresponds to a local iterator.
5405
5406 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
5407
5408 --Add <table_name>.value to the WHERE clause being generated.
5409
5410 RETURN arg_table_name(v_tExprArgumentName(j)) || '.node_value';
5411 ELSE
5412
5413 --Add <table_name>.i_<property_id> to the WHERE clause being generated.
5414 RETURN arg_table_name(v_tExprArgumentName(j)) || '.i_' ||
5415 TO_CHAR(EXTRACT_PROPERTY_INFO(j, propName, jChild, propType));
5416 END IF;
5417 ELSE
5418
5419 --This is an external argument, must be in the parameter scope.
5420 --We assume that it is of type 'node'.
5421
5422 v_extern := GENERATE_ARGUMENT(j, LocalType);
5423 IF(LocalType = DATA_TYPE_TEXT)THEN v_quotes := ''''; END IF;
5424
5425 IF(v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
5426
5427 RETURN v_quotes || PROPERTY_VALUE(v_ChildrenIndex(v_tExprId(j)), glIndexByPsNodeId(v_tExprPsNodeId(j)), LocalType) || v_quotes;
5428 ELSE
5429
5430 RETURN v_quotes || v_extern(1) || v_quotes;
5431 END IF;
5432 END IF;
5433 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_NODE AND v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
5434
5435 --Nodes can participate in the WHERE clause only with a property applied.
5436 --Bug #4648386.
5437
5438 v_extern(1) := EXTRACT_PROPERTY_INFO(j, propName, jChild, propType);
5439 nDebug := 7004032;
5440 IF(jChild IN (DATATYPE_TRANSLATABLE_PROP, DATA_TYPE_TEXT))THEN v_quotes := ''''; END IF;
5441
5442 IF(propType = 0)THEN
5443
5444 RETURN v_quotes || PROPERTY_VALUE(v_ChildrenIndex(v_tExprId(j)), glIndexByPsNodeId(v_tExprPsNodeId(j)), LocalType) || v_quotes;
5445 ELSE
5446
5447 RETURN v_quotes || STATIC_SYSPROP_VALUE(v_tExprPsNodeId(j), v_tExprPropertyId(j), propType) || v_quotes;
5448 END IF;
5449 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_LITERAL)THEN
5450
5451 bindValue(bindValue.COUNT + 1) := v_tExprDataValue(j);
5452 RETURN ':x' || TO_CHAR(bindValue.COUNT);
5453
5454 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_OPERATOR)THEN
5455
5456 jChild := v_ChildrenIndex(v_tExprId(j));
5457
5458 IF(v_tExprSubtype(j) = OPERATOR_TOTEXT)THEN
5459
5460 --Added for the bug #5620750. Just need ignore the ToText operator to continue using
5461 --default type conversion.
5462
5463 RETURN EXAMINE_WHERE_CLAUSE(jChild);
5464 END IF;
5465
5466 IF(v_tExprParentId.EXISTS(jChild + 1) AND v_tExprParentId(jChild + 1)= v_tExprId(j))THEN
5467
5468 IF(v_tExprSubtype(j) IN (OPERATOR_EQUALS,
5469 OPERATOR_NOTEQUALS,
5470 OPERATOR_EQUALS_INT,
5471 OPERATOR_NOTEQUALS_INT,
5472 OPERATOR_GT,
5473 OPERATOR_LT,
5474 OPERATOR_GE,
5475 OPERATOR_LE,
5476 OPERATOR_AND,
5477 OPERATOR_OR))THEN
5478
5479 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || OperatorLiterals(v_tExprSubtype(j)) ||
5480 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
5481
5482 ELSIF(v_tExprSubtype(j) = OPERATOR_CONCAT)THEN
5483
5484 RETURN EXAMINE_WHERE_CLAUSE(jChild) || ' || ' || EXAMINE_WHERE_CLAUSE(jChild + 1);
5485
5486 ELSIF(v_tExprSubtype(j) = OPERATOR_BEGINSWITH)THEN
5487
5488 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ' ||
5489 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
5490
5491 ELSIF(v_tExprSubtype(j) = OPERATOR_ENDSWITH)THEN
5492
5493 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ''%'' || ' ||
5494 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
5495
5496 ELSIF(v_tExprSubtype(j) = OPERATOR_CONTAINS)THEN
5497
5498 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ''%'' || ' ||
5499 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
5500
5501 ELSIF(v_tExprSubtype(j) = OPERATOR_LIKE)THEN
5502
5503 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ' ||
5504 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
5505
5506 ELSIF(v_tExprSubtype(j) = OPERATOR_MATCHES)THEN
5507
5508 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ' ||
5509 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
5510
5511 ELSIF(v_tExprSubtype(j) = OPERATOR_DOESNOTBEGINWITH)THEN
5512
5513 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ' ||
5514 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
5515
5516 ELSIF(v_tExprSubtype(j) = OPERATOR_DOESNOTENDWITH)THEN
5517
5518 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ''%'' || ' ||
5519 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
5520
5521 ELSIF(v_tExprSubtype(j) = OPERATOR_DOESNOTCONTAIN)THEN
5522
5523 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ''%'' || ' ||
5524 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
5525
5526 ELSIF(v_tExprSubtype(j) = OPERATOR_NOTLIKE)THEN
5527
5528 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ' ||
5529 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
5530
5531 ELSE
5532
5533 RAISE CZ_E_UKNOWN_OPER_IN_COMPAT;
5534 END IF;
5535
5536 ELSIF(v_tExprSubtype(j) = OPERATOR_NOT)THEN
5537
5538 RETURN '(NOT ' || EXAMINE_WHERE_CLAUSE(jChild) || ')';
5539
5540 ELSE
5541
5542 RAISE CZ_E_WRONG_OPER_IN_COMPAT;
5543 END IF;
5544 ELSE
5545
5546 RAISE CZ_R_WRONG_COMPAT_EXPRESSION;
5547 END IF;
5548 END;
5549 ---------------------------------------------------------------------------------------
5550 BEGIN
5551
5552 nDebug := 7004100;
5553
5554 nChild := v_ChildrenIndex(v_tExprId(j));
5555
5556 WHILE(v_tExprParentId(nChild) = v_tExprId(j)) LOOP
5557 IF(v_tExprType(nChild) = EXPR_ITERATOR)THEN
5558
5559 iteratorIndex(iteratorIndex.COUNT + 1) := nChild;
5560 ELSIF(v_tExprType(nChild) = EXPR_WHERE)THEN
5561
5562 whereIndex := nChild;
5563 ELSE
5564
5565 expressionIndex := nChild;
5566 END IF;
5567
5568 nChild := nChild + 1;
5569 END LOOP;
5570
5571 v_stack_start := parameterScope.COUNT + 1;
5572 v_stack_end := v_stack_start + iteratorIndex.COUNT - 1;
5573
5574 nDebug := 7004101;
5575
5576 FOR i IN 1..iteratorIndex.COUNT LOOP
5577
5578 bind_node_id.DELETE;
5579 bind_node_id_ex.DELETE;
5580 bind_node_type.DELETE;
5581 bind_node_value.DELETE;
5582 bind_node_obj.DELETE;
5583 bind_values.DELETE;
5584
5585 v_property_id.DELETE;
5586 v_data_type.DELETE;
5587 v_prop_name.DELETE;
5588 v_flag.DELETE;
5589
5590 temp_table_hash_key(forallLevel) := NULL;
5591 tableAlias := 'T' || TO_CHAR(i);
5592
5593 iterator.DELETE;
5594 iterator := GENERATE_ITERATOR(iteratorIndex(i), ListType);
5595
5596 IF(whereIndex <> 0)THEN
5597 EXPLORE_WHERE(whereIndex, v_tExprArgumentName(iteratorIndex(i)));
5598 END IF;
5599
5600 IF(temp_table_hash_key(forallLevel) IS NOT NULL)THEN
5601 FOR ii IN 1..v_property_id.COUNT LOOP
5602 temp_table_hash_key(forallLevel) := temp_table_hash_key(forallLevel) || '-' || TO_CHAR(v_property_id(ii));
5603 END LOOP;
5604 END IF;
5605
5606 nDebug := 7004102;
5607
5608 IF(temp_table_hash_key(forallLevel) IS NOT NULL AND temp_table_hash.EXISTS(temp_table_hash_key(forallLevel)))THEN
5609
5610 tableName := temp_table_hash(temp_table_hash_key(forallLevel));
5611 arg_table_name(v_tExprArgumentName(iteratorIndex(i))) := tableAlias;
5612
5613 IF(SQLSelect IS NULL)THEN SQLSelect := 'SELECT '; ELSE SQLSelect := SQLSelect || ', '; END IF;
5614 SQLSelect := SQLSelect || tableAlias || '.node_type, ' ||
5615 tableAlias || '.node_id, ' ||
5616 tableAlias || '.node_value, ' ||
5617 tableAlias || '.node_obj, ' ||
5618 tableAlias || '.node_id_ex';
5619 IF(SQLFrom IS NULL)THEN SQLFrom := ' FROM '; ELSE SQLFrom := SQLFrom || ', '; END IF;
5620 SQLFrom := SQLFrom || tableName || ' ' || tableAlias;
5621
5622 ELSE
5623
5624 --tableName := 'G_' || TO_CHAR(table_name_generator);
5625 -- SMANNA : Bug11822849 : Want to make these global temp table name unique between the sessions.
5626 tableName := 'G_' ||TO_CHAR(thisRunId)||'_'|| TO_CHAR(table_name_generator);
5627 table_name_generator := table_name_generator + 1;
5628 arg_table_name(v_tExprArgumentName(iteratorIndex(i))) := tableAlias;
5629
5630 IF(SQLSelect IS NULL)THEN SQLSelect := 'SELECT '; ELSE SQLSelect := SQLSelect || ', '; END IF;
5631 SQLSelect := SQLSelect || tableAlias || '.node_type, ' ||
5632 tableAlias || '.node_id, ' ||
5633 tableAlias || '.node_value, ' ||
5634 tableAlias || '.node_obj, ' ||
5635 tableAlias || '.node_id_ex';
5636 IF(SQLFrom IS NULL)THEN SQLFrom := ' FROM '; ELSE SQLFrom := SQLFrom || ', '; END IF;
5637 SQLFrom := SQLFrom || tableName || ' ' || tableAlias;
5638
5639 SQLCreate := 'CREATE GLOBAL TEMPORARY TABLE ' || tableName ||
5640 '(node_type NUMBER, node_id NUMBER, node_value VARCHAR2(' || TO_CHAR(MAXIMUM_INDEX_LENGTH) ||
5641 '), node_obj VARCHAR2(' || TO_CHAR(MAXIMUM_INDEX_LENGTH) || '), node_id_ex NUMBER';
5642
5643 FOR ii IN 1..v_property_id.COUNT LOOP
5644
5645 SQLCreate := SQLCreate || ', i_' || TO_CHAR(v_property_id(ii));
5646
5647 IF(v_data_type(ii) IN (DATA_TYPE_INTEGER, DATA_TYPE_DECIMAL))THEN
5648
5649 SQLCreate := SQLCreate || ' NUMBER';
5650 ELSE
5651
5652 SQLCreate := SQLCreate || ' VARCHAR2(' || TO_CHAR(MAXIMUM_INDEX_LENGTH) || ')';
5653 END IF;
5654 END LOOP;
5655
5656 SQLCreate := SQLCreate || ') ON COMMIT PRESERVE ROWS';
5657
5658 nDebug := 7004103;
5659
5660 BEGIN
5661 EXECUTE IMMEDIATE SQLCreate;
5662 EXCEPTION
5663 WHEN OTHERS THEN
5664
5665 --If the table already exists, truncate it, drop and try to create again.
5666
5667 IF(SQLCODE = ORACLE_OBJECT_ALREADY_EXISTS)THEN
5668 EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || tableName;
5669 EXECUTE IMMEDIATE 'DROP TABLE ' || tableName;
5670 EXECUTE IMMEDIATE SQLCreate;
5671 ELSE
5672 RAISE;
5673 END IF;
5674 END;
5675
5676 --The table is created, add its name to the delete list.
5677
5678 temp_tables(temp_tables.COUNT + 1) := tableName;
5679
5680 nDebug := 7004104;
5681
5682 SQLInsert := 'INSERT INTO ' || tableName || '(node_type, node_id, node_value, node_obj, node_id_ex';
5683 SQLValues := ' VALUES (:y1, :y2, :y3, :y4, :y5';
5684
5685 FOR ii IN 1..v_property_id.COUNT LOOP
5686
5687 BEGIN
5688
5689 EXECUTE IMMEDIATE 'CREATE INDEX ' || tableName || '_I' || TO_CHAR(ii) || ' ON ' || tableName ||
5690 '(i_' || v_property_id(ii) || ')';
5691 EXCEPTION
5692 WHEN OTHERS THEN
5693 IF(SQLCODE <> ORACLE_OBJECT_ALREADY_EXISTS)THEN RAISE; END IF;
5694 END;
5695
5696 SQLInsert := SQLInsert || ', i_' || TO_CHAR(v_property_id(ii));
5697 SQLValues := SQLValues || ', :x' || TO_CHAR(ii);
5698 END LOOP;
5699
5700 SQLInsert := SQLInsert || ')';
5701 SQLValues := SQLValues || ')';
5702
5703 nDebug := 7004105;
5704
5705 FOR ii IN 1..iterator.COUNT LOOP
5706
5707 IF(LENGTH(iterator(ii).node_value) > MAXIMUM_INDEX_LENGTH OR
5708 LENGTH(iterator(ii).node_obj) > MAXIMUM_INDEX_LENGTH)THEN
5709
5710 --Bug #3416994. This structure is internally generated, so we give the 'internal error' message.
5711 RAISE CZ_R_TYPE_NO_PROPERTY;
5712 END IF;
5713
5714 bind_node_id(ii) := iterator(ii).node_id;
5715 bind_node_id_ex(ii) := iterator(ii).node_id_ex;
5716 bind_node_value(ii) := iterator(ii).node_value;
5717 bind_node_obj(ii) := iterator(ii).node_obj;
5718 bind_node_type(ii) := iterator(ii).node_type;
5719
5720 IF(v_property_id.COUNT > 0)THEN
5721
5722 --This is only valid if there are properties.
5723
5724 IF(iterator(ii).node_id IS NULL)THEN RAISE CZ_R_TYPE_NO_PROPERTY; END IF;
5725
5726 nodeId := glPsNodeId(glIndexByPsNodeId(iterator(ii).node_id));
5727 itemId := glItemId(glIndexByPsNodeId(iterator(ii).node_id));
5728 END IF;
5729
5730 --Get the property values and insert the data.
5731
5732 FOR jj IN 1..v_property_id.COUNT LOOP
5733
5734 propertyId := v_property_id(jj);
5735 hash_propval_key := TO_CHAR(nodeId) || '-' || TO_CHAR(itemId) || '-' ||
5736 TO_CHAR(propertyId) || '-' || TO_CHAR(v_flag(propertyId));
5737
5738 IF(NOT table_hash_propval.EXISTS(hash_propval_key))THEN
5739
5740 IF(v_flag(propertyId) = 0)THEN
5741
5742 --User property.
5743
5744 propertyVal := GET_PROPERTY_VALUE(nodeId, propertyId, itemId, localNumber);
5745
5746 --Bug #4554100.
5747
5748 IF(localNumber IS NULL)THEN
5749
5750 errorMessage := v_prop_name(jj);
5751 auxIndex := glIndexByPsNodeId(iterator(ii).node_id);
5752 IF(glParentId(auxIndex) IS NULL)THEN nParam := auxIndex; ELSE
5753 nParam := glIndexByPsNodeId(glParentId(auxIndex)); END IF;
5754 RAISE CZ_R_OPTION_NO_PROPERTY;
5755 END IF;
5756 ELSE
5757
5758 --System property.
5759
5760 propertyVal := STATIC_SYSPROP_VALUE(nodeId, propertyId, v_flag(v_property_id(jj)));
5761 END IF;
5762
5763 IF(LENGTH(propertyVal) > MAXIMUM_INDEX_LENGTH)THEN
5764
5765 --Bug #3416994.
5766
5767 errorMessage := v_prop_name(jj);
5768 auxIndex := glIndexByPsNodeId(iterator(ii).node_id);
5769 IF(glParentId(auxIndex) IS NULL)THEN nParam := auxIndex; ELSE
5770 nParam := glIndexByPsNodeId(glParentId(auxIndex)); END IF;
5771 RAISE CZ_R_LONG_PROPERTY_VALUE;
5772 END IF;
5773
5774 bind_values(jj)(ii) := propertyVal;
5775 table_hash_propval(hash_propval_key) := propertyVal;
5776 ELSE
5777 bind_values(jj)(ii) := table_hash_propval(hash_propval_key);
5778 END IF;
5779 END LOOP;
5780 END LOOP;
5781
5782 nDebug := 7004106;
5783
5784 v_cursor := DBMS_SQL.OPEN_CURSOR;
5785 DBMS_SQL.PARSE(v_cursor, SQLInsert || SQLValues, DBMS_SQL.NATIVE);
5786
5787 DBMS_SQL.BIND_ARRAY(v_cursor, ':y1', bind_node_type);
5788 DBMS_SQL.BIND_ARRAY(v_cursor, ':y2', bind_node_id);
5789 DBMS_SQL.BIND_ARRAY(v_cursor, ':y3', bind_node_value);
5790 DBMS_SQL.BIND_ARRAY(v_cursor, ':y4', bind_node_obj);
5791 DBMS_SQL.BIND_ARRAY(v_cursor, ':y5', bind_node_id_ex);
5792
5793 FOR ii IN 1..v_property_id.COUNT LOOP
5794 DBMS_SQL.BIND_ARRAY(v_cursor, ':x' || TO_CHAR(ii), bind_values(ii));
5795 END LOOP;
5796
5797 localNumber := DBMS_SQL.EXECUTE(v_cursor);
5798 DBMS_SQL.CLOSE_CURSOR(v_cursor);
5799
5800 nDebug := 7004107;
5801
5802 EXECUTE IMMEDIATE 'ANALYZE TABLE ' || tableName || ' COMPUTE STATISTICS';
5803
5804 --The table is created and populated, add its name to the hash for re-use if it is eligible.
5805
5806 IF(temp_table_hash_key(forallLevel) IS NOT NULL)THEN temp_table_hash(temp_table_hash_key(forallLevel)) := tableName; END IF;
5807 END IF;
5808 END LOOP;
5809
5810 --Generate the WHERE clause and run the query with bind variables. For every row returned,
5811 --generate the expression and return the object.
5812 --To do this, add GENERATE_ARGUMENT to the GENERATE_EXPRESSION.
5813
5814 nDebug := 7004108;
5815
5816 IF(whereIndex <> 0)THEN
5817
5818 SQLWhere := ' WHERE ' || EXAMINE_WHERE_CLAUSE(v_ChildrenIndex(v_tExprId(whereIndex)));
5819 END IF;
5820
5821 v_cursor := DBMS_SQL.OPEN_CURSOR;
5822 DBMS_SQL.PARSE(v_cursor, SQLSelect || SQLFrom || SQLWhere, DBMS_SQL.NATIVE);
5823
5824 FOR i IN 1..bindValue.COUNT LOOP
5825 DBMS_SQL.BIND_VARIABLE(v_cursor, ':x' || TO_CHAR(i), bindValue(i));
5826 END LOOP;
5827
5828 FOR i IN 1..iteratorIndex.COUNT LOOP
5829
5830 DBMS_SQL.DEFINE_COLUMN(v_cursor, 5 * (i - 1) + 1, localNumber);
5831 DBMS_SQL.DEFINE_COLUMN(v_cursor, 5 * (i - 1) + 2, localNumber);
5832 DBMS_SQL.DEFINE_COLUMN(v_cursor, 5 * (i - 1) + 3, localString, 2000);
5833 DBMS_SQL.DEFINE_COLUMN(v_cursor, 5 * (i - 1) + 4, localString, 2000);
5834 DBMS_SQL.DEFINE_COLUMN(v_cursor, 5 * (i - 1) + 5, localNumber);
5835 END LOOP;
5836
5837 nDebug := 7004109;
5838
5839 localNumber := DBMS_SQL.EXECUTE(v_cursor);
5840
5841 --For every returned row, store the values in the parameter scope, from where GENERATE_EXPRESSION
5842 --will be retrieving it when generating an argument.
5843
5844 FOR i IN 1..iteratorIndex.COUNT LOOP
5845
5846 parameterName(v_stack_start + i - 1) := v_tExprArgumentName(iteratorIndex(i));
5847 END LOOP;
5848
5849 WHILE(DBMS_SQL.FETCH_ROWS(v_cursor) > 0)LOOP
5850
5851 FOR i IN 1..iteratorIndex.COUNT LOOP
5852
5853 DBMS_SQL.COLUMN_VALUE(v_cursor, 5 * (i - 1) + 1, parameterScope(v_stack_start + i - 1).node_type);
5854 DBMS_SQL.COLUMN_VALUE(v_cursor, 5 * (i - 1) + 2, parameterScope(v_stack_start + i - 1).node_id);
5855 DBMS_SQL.COLUMN_VALUE(v_cursor, 5 * (i - 1) + 3, parameterScope(v_stack_start + i - 1).node_value);
5856 DBMS_SQL.COLUMN_VALUE(v_cursor, 5 * (i - 1) + 4, parameterScope(v_stack_start + i - 1).node_obj);
5857 DBMS_SQL.COLUMN_VALUE(v_cursor, 5 * (i - 1) + 5, parameterScope(v_stack_start + i - 1).node_id_ex);
5858 END LOOP;
5859
5860 IF(expressionIndex <> 0 AND v_ChildrenIndex.EXISTS(v_tExprId(expressionIndex)))THEN
5861
5862 --Bug #5497235. This is a FORALL with an expression, need to generate the expression.
5863
5864 generateCollect := 1;
5865
5866 v_express := GENERATE_EXPRESSION(expressionIndex, ListType);
5867 generateCollect := 0;
5868
5869 nCount := v_return.COUNT + 1;
5870
5871 FOR i IN 1..v_express.COUNT LOOP
5872
5873 IF(v_tExprType(j) = EXPR_FORALL_DISTINCT)THEN
5874
5875 --For COLLECT DISTINCT we need to leave only distinct values in the results.
5876
5877 v_value_exists := 0;
5878
5879 FOR ii IN 1..nCount - 1 LOOP
5880 IF(v_return(ii).node_value = v_express(i))THEN v_value_exists := 1; EXIT; END IF;
5881 END LOOP;
5882 END IF;
5883
5884 IF(v_value_exists = 0)THEN
5885
5886 v_return(nCount).node_obj := v_express(i);
5887 v_return(nCount).node_value := v_express(i);
5888 v_return(nCount).node_id := NULL;
5889 v_return(nCount).node_type := DATA_TYPE_VARIANT;
5890 nCount := nCount + 1;
5891 END IF;
5892 END LOOP;
5893
5894 ELSE
5895
5896 --Bug #5497235. This is a COLLECT because there is no expression or the expression is just an argument.
5897 --In this case we need a direct copy of the parameter scope.
5898
5899 nCount := v_return.COUNT + 1;
5900
5901 /* Changing this for loop from 1..parameterscope.count to the below as part of the fix for the bug : 6355526*/
5902
5903 FOR i IN v_stack_start..v_stack_end LOOP
5904
5905
5906 v_return(nCount).node_id := parameterScope(i).node_id;
5907 v_return(nCount).node_type := parameterScope(i).node_type;
5908 v_return(nCount).node_value := parameterScope(i).node_value;
5909 v_return(nCount).node_obj := parameterScope(i).node_obj;
5910 v_return(nCount).node_id_ex := parameterScope(i).node_id_ex;
5911 nCount := nCount + 1;
5912 END LOOP;
5913 END IF;
5914 END LOOP;
5915
5916 parameterScope.DELETE(v_stack_start, v_stack_end);
5917 parameterName.DELETE(v_stack_start, v_stack_end);
5918
5919 nDebug := 7004110;
5920
5921 DBMS_SQL.CLOSE_CURSOR(v_cursor);
5922
5923 IF(v_tExprParentId(j) IS NOT NULL AND v_return.COUNT = 0)THEN
5924
5925 --The FORALL or COLLECT did not yield any rows while it is not the root operator.
5926 --Need a new message to report this.
5927
5928 RAISE CZ_R_COMPAT_NO_COMBINATIONS;
5929 END IF;
5930
5931 RETURN v_return;
5932 END;
5933 ---------------------------------------------------------------------------------------
5934 --This function is introduced to support the level of embedding.
5935
5936 FUNCTION GENERATE_FORALL(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tIteratorArray IS
5937 v_return tIteratorArray;
5938 BEGIN
5939 forallLevel := forallLevel + 1;
5940 v_return := GENERATE_FORALL_(j, ListType);
5941 forallLevel := forallLevel - 1;
5942 RETURN v_return;
5943 EXCEPTION
5944 WHEN OTHERS THEN
5945 forallLevel := forallLevel - 1;
5946 RAISE;
5947 END;
5948 ---------------------------------------------------------------------------------------
5949 FUNCTION GENERATE_COMPATIBLE_(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
5950
5951 iteratorIndex tIntegerArray;
5952 iterator tIteratorArray;
5953 whereIndex PLS_INTEGER := 0;
5954 featureIndex PLS_INTEGER;
5955 nChild NUMBER; -- jonatara:bug7041718
5956 nCounter NUMBER; -- jonatara:bug7041718
5957 v_property_id tIntegerArray;
5958 v_data_type tIntegerArray;
5959 v_prop_name tStringArray;
5960 v_return tStringArray;
5961 SQLCreate VARCHAR2(8000);
5962 SQLInsert VARCHAR2(8000);
5963 SQLValues VARCHAR2(8000);
5964 SQLSelect VARCHAR2(8000);
5965 SQLFrom VARCHAR2(8000);
5966 SQLWhere VARCHAR2(8000) := NULL;
5967 tableName VARCHAR2(4000);
5968 tableAlias VARCHAR2(4000);
5969 nodeId NUMBER; -- jonatara:bug7041718
5970 itemId PLS_INTEGER;
5971 propertyId PLS_INTEGER;
5972 c_values refCursor;
5973 v_cursor NUMBER;
5974 propertyVal VARCHAR2(4000);
5975 localNumber NUMBER;
5976 localString VARCHAR2(4000);
5977 bindValue tStringArray;
5978 typeCheck NUMBER;
5979 v_tOptionId DBMS_SQL.NUMBER_TABLE;
5980 v_tFeatureId tExplNodeId;
5981 v_BackIndex tIntegerArray;
5982 v_tExplId tExplNodeId;
5983 rowThreshold PLS_INTEGER := 0;
5984 v_OptionExists tIntegerArray_idx_vc2; --kdande; Bug 6881902; 11-Mar-2008
5985 v_OptionsChain tIntegerArray;
5986 v_FeatureIndex tIntegerArray;
5987 v_ItemIndex tIntegerArray;
5988 chainIndex PLS_INTEGER := 1;
5989 currentIndex PLS_INTEGER;
5990 itemIndex PLS_INTEGER;
5991 itemCount PLS_INTEGER := 1;
5992 v_RowLines tStringArray;
5993 v_ItemLines tStringArray;
5994 ExcludesRequired PLS_INTEGER;
5995 v_flag tIntegerArray;
5996
5997 bind_node_id DBMS_SQL.NUMBER_TABLE;
5998
5999 TYPE bind_value_table IS TABLE OF DBMS_SQL.VARCHAR2_TABLE INDEX BY BINARY_INTEGER;
6000 bind_values bind_value_table;
6001 arg_table_name temp_table_hash_type;
6002
6003 h_OptionExplId table_of_tNumberArray_idx_vc2;-- jonatara:bug7041718
6004 hash_propval_key VARCHAR2(4000);
6005 ---------------------------------------------------------------------------------------
6006 PROCEDURE EXPLORE_WHERE(j IN PLS_INTEGER, v_argument IN VARCHAR2) IS
6007 nChild PLS_INTEGER;
6008 nCount PLS_INTEGER;
6009 propertyId PLS_INTEGER;
6010 dataType PLS_INTEGER;
6011 propType PLS_INTEGER;
6012 propName cz_properties.name%TYPE;
6013 BEGIN
6014
6015 nDebug := 7005020;
6016
6017 nChild := v_ChildrenIndex(v_tExprId(j));
6018
6019 WHILE(v_tExprParentId(nChild) = v_tExprId(j))LOOP
6020
6021 nCount := v_property_id.COUNT + 1;
6022
6023 IF(v_ChildrenIndex.EXISTS(v_tExprId(nChild)))THEN
6024 IF(v_tExprType(nChild) = EXPR_ARGUMENT AND v_tExprArgumentName(nChild) = v_argument)THEN
6025
6026 propertyId := EXTRACT_PROPERTY_INFO(nChild, propName, dataType, propType);
6027 nDebug := 7005021;
6028 IF(NOT v_flag.EXISTS(propertyId))THEN
6029
6030 v_property_id(nCount) := propertyId;
6031 v_data_type(nCount) := dataType;
6032 v_prop_name(nCount) := propName;
6033 v_flag(propertyId) := propType;
6034 END IF;
6035 ELSE
6036
6037 EXPLORE_WHERE(nChild, v_argument);
6038 END IF;
6039 END IF;
6040 nChild := nChild + 1;
6041 END LOOP;
6042
6043 nDebug := 7005029;
6044 END;
6045 ---------------------------------------------------------------------------------------
6046 --This function finds every reference to iterators in the FORALL WHERE clause, replaces
6047 --arguments with 'G_<argument_name>.value' string and reference nodes with
6048 --'G_<argument_name>.i_<property_id>' string. It returns the generated SQL
6049 --WHERE clause of the SELECT statement.
6050 --All the literal values are collected in an array for later binding.
6051
6052 FUNCTION EXAMINE_WHERE_CLAUSE(j IN PLS_INTEGER) RETURN VARCHAR2 IS
6053 argChild PLS_INTEGER;
6054 propType PLS_INTEGER;
6055 jChild PLS_INTEGER;
6056 propName cz_properties.name%TYPE;
6057 LocalType PLS_INTEGER := DATA_TYPE_VOID;
6058 v_extern tStringArray;
6059 v_quotes VARCHAR2(2);
6060 BEGIN
6061
6062 nDebug := 7005030;
6063
6064 IF(v_tExprType(j) = EXPR_ARGUMENT)THEN
6065 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
6066
6067 --Add <table_name>.value to the WHERE clause being generated.
6068
6069 RETURN arg_table_name(v_tExprArgumentName(j)) || '.node_value';
6070 ELSE
6071
6072 --Add <table_name>.i_<property_id> to the WHERE clause being generated.
6073 RETURN arg_table_name(v_tExprArgumentName(j)) || '.i_' ||
6074 TO_CHAR(EXTRACT_PROPERTY_INFO(j, propName, jChild, propType));
6075 END IF;
6076 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_NODE AND v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
6077
6078 --Nodes can participate in the WHERE clause only with a property applied.
6079 --Bug #4648386.
6080
6081 v_extern(1) := EXTRACT_PROPERTY_INFO(j, propName, jChild, propType);
6082
6083 nDebug := 7005032;
6084
6085 IF(jChild IN (DATATYPE_TRANSLATABLE_PROP, DATA_TYPE_TEXT))THEN v_quotes := ''''; END IF;
6086
6087 IF(propType = 0)THEN
6088
6089 RETURN v_quotes || PROPERTY_VALUE(v_ChildrenIndex(v_tExprId(j)), glIndexByPsNodeId(v_tExprPsNodeId(j)), LocalType) || v_quotes;
6090 ELSE
6091
6092 RETURN v_quotes || STATIC_SYSPROP_VALUE(v_tExprPsNodeId(j), v_tExprPropertyId(j), propType) || v_quotes;
6093 END IF;
6094 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_LITERAL)THEN
6095
6096 bindValue(bindValue.COUNT + 1) := v_tExprDataValue(j);
6097 RETURN ':x' || TO_CHAR(bindValue.COUNT);
6098
6099 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_OPERATOR)THEN
6100
6101 jChild := v_ChildrenIndex(v_tExprId(j));
6102
6103 IF(v_tExprSubtype(j) = OPERATOR_TOTEXT)THEN
6104
6105 --Added for the bug #5620750. Just need to ignore the ToText operator to preserve the
6106 --default type conversion.
6107
6108 RETURN EXAMINE_WHERE_CLAUSE(jChild);
6109 END IF;
6110
6111 IF(v_tExprParentId.EXISTS(jChild + 1) AND v_tExprParentId(jChild + 1)= v_tExprId(j))THEN
6112
6113 IF(v_tExprSubtype(j) IN (OPERATOR_EQUALS,
6114 OPERATOR_NOTEQUALS,
6115 OPERATOR_EQUALS_INT,
6116 OPERATOR_NOTEQUALS_INT,
6117 OPERATOR_GT,
6118 OPERATOR_LT,
6119 OPERATOR_GE,
6120 OPERATOR_LE,
6121 OPERATOR_AND,
6122 OPERATOR_OR))THEN
6123
6124 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || OperatorLiterals(v_tExprSubtype(j)) ||
6125 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
6126
6127 ELSIF(v_tExprSubtype(j) = OPERATOR_CONCAT)THEN
6128
6129 RETURN EXAMINE_WHERE_CLAUSE(jChild) || ' || ' || EXAMINE_WHERE_CLAUSE(jChild + 1);
6130
6131 ELSIF(v_tExprSubtype(j) = OPERATOR_BEGINSWITH)THEN
6132
6133 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ' ||
6134 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
6135
6136 ELSIF(v_tExprSubtype(j) = OPERATOR_ENDSWITH)THEN
6137
6138 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ''%'' || ' ||
6139 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
6140
6141 ELSIF(v_tExprSubtype(j) = OPERATOR_CONTAINS)THEN
6142
6143 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ''%'' || ' ||
6144 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
6145
6146 ELSIF(v_tExprSubtype(j) = OPERATOR_LIKE)THEN
6147
6148 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ' ||
6149 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
6150
6151 ELSIF(v_tExprSubtype(j) = OPERATOR_MATCHES)THEN
6152
6153 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ' ||
6154 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
6155
6156 ELSIF(v_tExprSubtype(j) = OPERATOR_DOESNOTBEGINWITH)THEN
6157
6158 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ' ||
6159 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
6160
6161 ELSIF(v_tExprSubtype(j) = OPERATOR_DOESNOTENDWITH)THEN
6162
6163 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ''%'' || ' ||
6164 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
6165
6166 ELSIF(v_tExprSubtype(j) = OPERATOR_DOESNOTCONTAIN)THEN
6167
6168 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ''%'' || ' ||
6169 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
6170
6171 ELSIF(v_tExprSubtype(j) = OPERATOR_NOTLIKE)THEN
6172
6173 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ' ||
6174 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
6175
6176 ELSE
6177
6178 RAISE CZ_E_UKNOWN_OPER_IN_COMPAT;
6179 END IF;
6180
6181 ELSIF(v_tExprSubtype(j) = OPERATOR_NOT)THEN
6182
6183 RETURN '(NOT ' || EXAMINE_WHERE_CLAUSE(jChild) || ')';
6184
6185 ELSE
6186
6187 RAISE CZ_E_WRONG_OPER_IN_COMPAT;
6188 END IF;
6189 ELSE
6190
6191 RAISE CZ_R_WRONG_COMPAT_EXPRESSION;
6192 END IF;
6193 END;
6194 ---------------------------------------------------------------------------------------
6195 PROCEDURE GET_ITEM_INDEX(OptionId IN NUMBER, ColumnIndex IN PLS_INTEGER) IS --kdande; Bug 6881902; 11-Mar-2008
6196 BEGIN
6197
6198 IF(NOT v_OptionExists.EXISTS(OptionId))THEN
6199 v_OptionExists(OptionId) := chainIndex;
6200 ELSE
6201 currentIndex := v_OptionExists(OptionId);
6202 LOOP
6203
6204 IF(v_FeatureIndex(currentIndex) = ColumnIndex)THEN
6205 itemIndex := v_ItemIndex(currentIndex);
6206 RETURN;
6207 END IF;
6208
6209 EXIT WHEN v_OptionsChain(currentIndex) IS NULL;
6210 currentIndex := v_OptionsChain(currentIndex);
6211 END LOOP;
6212
6213 v_OptionsChain(currentIndex) := chainIndex;
6214 END IF;
6215
6216 --Bug #4546828. Use the hashed explosion id for each option.
6217
6218 v_ItemLines(itemCount) := GENERATE_NAME_EXPL(h_OptionExplId(ColumnIndex)(OptionId), OptionId) || ' ' || TO_CHAR(ColumnIndex - 1);
6219
6220 v_OptionsChain(chainIndex) := NULL;
6221 v_FeatureIndex(chainIndex) := ColumnIndex;
6222 v_ItemIndex(chainIndex) := itemCount;
6223 itemIndex := itemCount;
6224 itemCount := itemCount + 1;
6225 chainIndex := chainIndex + 1;
6226 END;
6227 ---------------------------------------------------------------------------------------
6228 PROCEDURE GENERATE_STANDARD_PBC IS
6229 BEGIN
6230 v_cursor := DBMS_SQL.OPEN_CURSOR;
6231 DBMS_SQL.PARSE(v_cursor, SQLSelect || SQLFrom || SQLWhere, DBMS_SQL.NATIVE);
6232
6233 FOR i IN 1..bindValue.COUNT LOOP
6234 DBMS_SQL.BIND_VARIABLE(v_cursor, ':x' || TO_CHAR(i), bindValue(i));
6235 END LOOP;
6236
6237 nDebug := 7005109;
6238
6239 localNumber := DBMS_SQL.EXECUTE(v_cursor);
6240
6241 LOOP
6242
6243 FOR i IN 1..iteratorIndex.COUNT LOOP
6244 DBMS_SQL.DEFINE_ARRAY(v_cursor, i, v_tOptionId, DBMS_SQL_MAX_BUFFER_SIZE, 1);
6245 END LOOP;
6246
6247 localNumber := DBMS_SQL.FETCH_ROWS(v_cursor);
6248
6249 FOR i IN 1..v_tFeatureId.COUNT LOOP
6250
6251 DBMS_SQL.COLUMN_VALUE(v_cursor, i, v_tOptionId);
6252
6253 FOR n IN 1..localNumber LOOP
6254
6255 GET_ITEM_INDEX(v_tOptionId(n), i);
6256
6257 --Fix for the bug #2256166: changed n to rowThreshold + n in the EXISTS operator.
6258
6259 IF(v_RowLines.EXISTS(rowThreshold + n))THEN
6260 v_RowLines(rowThreshold + n) := v_RowLines(rowThreshold + n) || ' ' || TO_CHAR(itemIndex - 1);
6261 ELSE
6262 v_RowLines(rowThreshold + n) := ' ' || TO_CHAR(itemIndex - 1);
6263 END IF;
6264 END LOOP;
6265 END LOOP;
6266 EXIT WHEN localNumber <> DBMS_SQL_MAX_BUFFER_SIZE;
6267 rowThreshold := rowThreshold + DBMS_SQL_MAX_BUFFER_SIZE;
6268 END LOOP;
6269
6270 nDebug := 7005110;
6271
6272 DBMS_SQL.CLOSE_CURSOR(v_cursor);
6273
6274 --If there's no valid combinations, report the rule and ignore it.
6275
6276 IF(v_RowLines.COUNT = 0)THEN
6277 RAISE CZ_R_COMPAT_NO_COMBINATIONS;
6278 END IF;
6279
6280 --Generate the combo structure
6281
6282 vLogicLine := 'OBJECT P_R' || TO_CHAR(nRuleId) || '_' || TO_CHAR(v_tExprId(j)) || NewLine ||
6283 'COMBO P_R' || TO_CHAR(nRuleId) || '_' || TO_CHAR(v_tExprId(j)) || ' ' ||
6284 TO_CHAR(v_ItemLines.COUNT) || ' ' || TO_CHAR(v_RowLines.COUNT) || ' ' ||
6285 TO_CHAR(v_tFeatureId.COUNT) || ' ... ' || TO_CHAR(nReasonId) || NewLine;
6286 PACK;
6287
6288 FOR i IN 1..v_ItemLines.COUNT LOOP
6289
6290 vLogicLine := 'CI ' || TO_CHAR(i - 1) || ' ' || v_ItemLines(i) || NewLine;
6291 PACK;
6292 END LOOP;
6293
6294 FOR i IN 1..v_tFeatureId.COUNT LOOP
6295
6296 IF(GenerateGatedCombo = 0)THEN
6297
6298 --Use intermediate variable instead of using NVL because this is faster
6299
6300 localNumber := glIndexByPsNodeId(v_tFeatureId(i));
6301 localString := TO_CHAR(glMaximum(localNumber));
6302
6303 --If it's a BOM item, we use maximum_selected instead of maximum
6304
6305 IF(glPsNodeType(localNumber) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
6306 localString := TO_CHAR(glMaximumSel(localNumber));
6307 END IF;
6308
6309 IF(localString IS NULL)THEN localString := '-1'; END IF;
6310 vLogicLine := ' O';
6311 ELSE
6312
6313 --Generate gated combinations: maximum is always -1, the 'G' argument is followed
6314 --by the feature name.
6315
6316 localString := '-1';
6317 vLogicLine := ' G ' || GENERATE_NAME(v_BackIndex(i), v_tFeatureId(i));
6318 END IF;
6319
6320 vLogicLine := 'CC ' || TO_CHAR(i - 1) || ' 0 ' || localString || vLogicLine || NewLine;
6321 PACK;
6322 END LOOP;
6323
6324 FOR i IN 1..v_RowLines.COUNT LOOP
6325
6326 vLogicLine := 'CR ' || TO_CHAR(i - 1) || v_RowLines(i) || NewLine;
6327 PACK;
6328 END LOOP;
6329
6330 vLogicLine := 'COMBO_END' || NewLine;
6331 PACK;
6332
6333 --Generate the exclude relations if necessary.
6334 --The code is re-written as part of the fix for the bug #4546828 to use the new hash table.
6335
6336 FOR i IN 1..v_tFeatureId.COUNT LOOP
6337
6338 --We will use this array in the local context now
6339
6340 v_OptionExists.DELETE;
6341
6342 FOR n IN 1..v_ItemLines.COUNT LOOP
6343
6344 itemIndex := INSTR(v_ItemLines(n), ' ', -1) + 1;
6345
6346 IF(TO_NUMBER(SUBSTR(v_ItemLines(n), itemIndex)) = i - 1)THEN
6347
6348 currentIndex := INSTR(v_ItemLines(n), '_', -1) + 1;
6349 v_OptionExists(TO_NUMBER(SUBSTR(v_ItemLines(n), currentIndex, itemIndex - currentIndex - 1))) := 1;
6350 END IF;
6351 END LOOP;
6352
6353 ExcludesRequired := 0;
6354 nChild := h_OptionExplId(i).FIRST;
6355 nCounter := nChild;
6356
6357 WHILE(nChild IS NOT NULL) LOOP
6358 IF(NOT v_OptionExists.EXISTS(glPersistentId(nChild)))THEN
6359 ExcludesRequired := 1;
6360 EXIT;
6361 END IF;
6362 nChild := h_OptionExplId(i).NEXT(nChild);
6363 END LOOP;
6364
6365 IF(ExcludesRequired = 1)THEN
6366
6367 nChild := nCounter;
6368
6369 vLogicLine := 'GS E ... ' || TO_CHAR(nReasonId) || NewLine || 'GL N ';
6370 PACK;
6371
6372 WHILE(nChild IS NOT NULL) LOOP
6373 IF(NOT v_OptionExists.EXISTS(glPersistentId(nChild)))THEN
6374 vLogicLine := GENERATE_NAME_EXPL(h_OptionExplId(i)(nChild), nChild) || ' ';
6375 PACK;
6376 END IF;
6377 nChild := h_OptionExplId(i).NEXT(nChild);
6378 END LOOP;
6379
6380 vLogicLine := NewLine || 'GR L ';
6381 PACK;
6382
6383 FOR n IN 1..v_tFeatureId.COUNT LOOP
6384 IF(n <> i)THEN
6385 vLogicLine := GENERATE_NAME(v_BackIndex(n), v_tFeatureId(n)) || ' ';
6386 PACK;
6387 END IF;
6388 END LOOP;
6389
6390 vLogicLine := NewLine;
6391 PACK;
6392 END IF; --Excludes required
6393 END LOOP;
6394 END GENERATE_STANDARD_PBC;
6395 ---------------------------------------------------------------------------------------
6396 PROCEDURE GENERATE_OPTIMIZED_PBC IS
6397
6398 TYPE tVarcharTable IS TABLE OF VARCHAR2(32000) INDEX BY VARCHAR2(32000);
6399
6400 v_options SYSTEM.cz_lce_compat_tab_type := SYSTEM.cz_lce_compat_tab_type();
6401 a_min PLS_INTEGER;
6402 b_min PLS_INTEGER;
6403 a_object_name VARCHAR2(4000);
6404 b_object_name VARCHAR2(4000);
6405 v_option_a DBMS_SQL.NUMBER_TABLE;
6406 v_option_b DBMS_SQL.NUMBER_TABLE;
6407 current_option NUMBER;
6408 v_bitpos_a tIntegerArray_idx_vc2; --jonatara:bug7041718
6409 v_bitpos_b tIntegerArray_idx_vc2;
6410 v_bitinv_a tIntegerArray;
6411 v_bitinv_b tIntegerArray;
6412 v_mask VARCHAR2(32000);
6413 v_group VARCHAR2(32000);
6414 v_rel VARCHAR2(1);
6415 v_group_by_set_mask_a tVarcharTable;
6416 v_group_by_set_mask_b tVarcharTable;
6417 /*-------------------------------------------------------------------------------------
6418 CREATE OR REPLACE TYPE cz_lce_compat_rec_type IS OBJECT (option_a NUMBER, option_b NUMBER);
6419 CREATE OR REPLACE TYPE cz_lce_compat_tab_type IS TABLE OF cz_lce_compat_rec_type;
6420 ---------------------------------------------------------------------------------------*/
6421 FUNCTION get_feature_minimum(p_feature_id IN NUMBER) RETURN PLS_INTEGER IS
6422 v_idx NUMBER; --kdande; Bug 6881902; 11-Mar-2008
6423 v_min NUMBER; --kdande; Bug 6881902; 11-Mar-2008
6424 BEGIN
6425 v_idx := glIndexByPsNodeId(p_feature_id);
6426 v_min := glMinimum(v_idx);
6427
6428 IF(glPsNodeType(v_idx) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
6429 v_min := glMinimumSel(v_idx);
6430 END IF;
6431 if(v_min IS NULL OR v_min < 1)THEN RETURN 0; END IF;
6432 RETURN 1;
6433 END;
6434 ---------------------------------------------------------------------------------------
6435 PROCEDURE init_set_mask(p_size IN PLS_INTEGER) IS
6436 BEGIN
6437 v_mask := '0';
6438 v_mask := RPAD(v_mask, p_size, '0');
6439 END;
6440 ---------------------------------------------------------------------------------------
6441 PROCEDURE set_mask(p_bitpos IN PLS_INTEGER) IS
6442 BEGIN
6443 v_mask := SUBSTR(v_mask, 1, p_bitpos - 1) || '1' || SUBSTR(v_mask, p_bitpos + 1);
6444 END;
6445 ---------------------------------------------------------------------------------------
6446 PROCEDURE init_group_mask_a(p_key IN VARCHAR2) IS
6447 BEGIN
6448 v_group_by_set_mask_a(p_key) := '0';
6449 v_group_by_set_mask_a(p_key) := RPAD(v_group_by_set_mask_a(p_key), v_bitpos_a.COUNT, '0');
6450 END;
6451 ---------------------------------------------------------------------------------------
6452 PROCEDURE set_group_mask_a(p_key IN VARCHAR2, p_bitpos IN PLS_INTEGER) IS
6453 BEGIN
6454 v_group_by_set_mask_a(p_key) := SUBSTR(v_group_by_set_mask_a(p_key), 1, p_bitpos - 1)
6455 || '1' || SUBSTR(v_group_by_set_mask_a(p_key), p_bitpos + 1);
6456 END;
6457 ---------------------------------------------------------------------------------------
6458 PROCEDURE init_group_mask_b(p_key IN VARCHAR2) IS
6459 BEGIN
6460 v_group_by_set_mask_b(p_key) := '0';
6461 v_group_by_set_mask_b(p_key) := RPAD(v_group_by_set_mask_b(p_key), v_bitpos_b.COUNT, '0');
6462 END;
6463 ---------------------------------------------------------------------------------------
6464 PROCEDURE set_group_mask_b(p_key IN VARCHAR2, p_bitpos IN PLS_INTEGER) IS
6465 BEGIN
6466 v_group_by_set_mask_b(p_key) := SUBSTR(v_group_by_set_mask_b(p_key), 1, p_bitpos - 1)
6467 || '1' || SUBSTR(v_group_by_set_mask_b(p_key), p_bitpos + 1);
6468 END;
6469 ---------------------------------------------------------------------------------------
6470 FUNCTION in_mask(p_bitpos IN PLS_INTEGER) RETURN BOOLEAN IS
6471 BEGIN
6472 RETURN (SUBSTR(v_mask, p_bitpos, 1) = '1');
6473 END;
6474 ---------------------------------------------------------------------------------------
6475 FUNCTION in_group(p_bitpos IN PLS_INTEGER) RETURN BOOLEAN IS
6476 BEGIN
6477 RETURN (SUBSTR(v_group, p_bitpos, 1) = '1');
6478 END;
6479 ---------------------------------------------------------------------------------------
6480 BEGIN
6481 nDebug := 8000000;
6482 v_cursor := DBMS_SQL.OPEN_CURSOR;
6483 DBMS_SQL.PARSE(v_cursor, SQLSelect || SQLFrom || SQLWhere, DBMS_SQL.NATIVE);
6484
6485 FOR i IN 1..bindValue.COUNT LOOP
6486 DBMS_SQL.BIND_VARIABLE(v_cursor, ':x' || TO_CHAR(i), bindValue(i));
6487 END LOOP;
6488
6489 localNumber := DBMS_SQL.EXECUTE(v_cursor);
6490 nDebug := 8000001;
6491 LOOP
6492
6493 DBMS_SQL.DEFINE_ARRAY(v_cursor, 1, v_option_a, DBMS_SQL_MAX_BUFFER_SIZE, 1);
6494 DBMS_SQL.DEFINE_ARRAY(v_cursor, 2, v_option_b, DBMS_SQL_MAX_BUFFER_SIZE, 1);
6495
6496 localNumber := DBMS_SQL.FETCH_ROWS(v_cursor);
6497
6498 DBMS_SQL.COLUMN_VALUE(v_cursor, 1, v_option_a);
6499 DBMS_SQL.COLUMN_VALUE(v_cursor, 2, v_option_b);
6500 nDebug := 8000002;
6501 FOR i IN 1..localNumber LOOP
6502 v_options.EXTEND();
6503 v_options(rowThreshold + i) := SYSTEM.cz_lce_compat_rec_type(v_option_a(i), v_option_b(i));
6504 nDebug := 8000003;
6505 --These arrays store 'bit positions' for every a or b option. Later they will be used in construction
6506 --of the 'bit masks' for compatibility groups and sets.
6507 --The 'inv' arrays allow to quickly get an option_id by its bit position.
6508
6509 IF(NOT v_bitpos_a.EXISTS(v_option_a(i)))THEN
6510
6511 v_bitpos_a(v_option_a(i)) := v_bitpos_a.COUNT + 1;
6512 v_bitinv_a(v_bitpos_a(v_option_a(i))) := v_option_a(i);
6513 END IF;
6514 IF(NOT v_bitpos_b.EXISTS(v_option_b(i)))THEN
6515
6516 v_bitpos_b(v_option_b(i)) := v_bitpos_b.COUNT + 1;
6517 v_bitinv_b(v_bitpos_b(v_option_b(i))) := v_option_b(i);
6518 END IF;
6519 END LOOP;
6520
6521 v_option_a.DELETE;
6522 v_option_b.DELETE;
6523
6524 EXIT WHEN localNumber <> DBMS_SQL_MAX_BUFFER_SIZE;
6525 rowThreshold := rowThreshold + DBMS_SQL_MAX_BUFFER_SIZE;
6526 END LOOP;
6527 nDebug := 8000005;
6528 DBMS_SQL.CLOSE_CURSOR(v_cursor);
6529
6530 --If there's no valid combinations, report the rule and ignore it.
6531
6532 IF(v_options.COUNT = 0)THEN
6533 RAISE CZ_R_COMPAT_NO_COMBINATIONS;
6534 END IF;
6535
6536 IF (v_options.COUNT = (featOptionsCount(v_tFeatureId(1)) * featOptionsCount(v_tFeatureId(2)))) THEN
6537
6538 --This is a two-column pbc rule, and the number of valid combinations is equal to the
6539 --number of possible combinations. The rule can be ignored.
6540
6541 RETURN;
6542 END IF;
6543
6544 a_min := get_feature_minimum(v_tFeatureId(1));
6545 b_min := get_feature_minimum(v_tFeatureId(2));
6546
6547 --Generate the main relations.
6548
6549 IF(a_min = 0)THEN
6550
6551 --We need a temporary object to represent Not(A).
6552
6553 nLocalDefaults := nLocalDefaults + 1;
6554 a_object_name := t_prefix || TO_CHAR(nLocalDefaults);
6555
6556 vLogicLine := 'OBJECT ' || a_object_name || NewLine ||
6557 'GS N ... ' || TO_CHAR(nReasonId) || NewLine ||
6558 'GL' || OperatorLetters(OPERATOR_ANYOF) || GENERATE_NAME(v_BackIndex(1), v_tFeatureId(1)) || NewLine ||
6559 'GR' || OperatorLetters(OPERATOR_ANYOF) || a_object_name || NewLine;
6560 PACK;
6561 a_object_name := a_object_name || ' ';
6562 END IF;
6563
6564 IF(b_min = 0)THEN
6565
6566 --We need a temporary object to represent Not(B).
6567
6568 nLocalDefaults := nLocalDefaults + 1;
6569 b_object_name := t_prefix || TO_CHAR(nLocalDefaults);
6570
6571 vLogicLine := 'OBJECT ' || b_object_name || NewLine ||
6572 'GS N ... ' || TO_CHAR(nReasonId) || NewLine ||
6573 'GL' || OperatorLetters(OPERATOR_ANYOF) || GENERATE_NAME(v_BackIndex(2), v_tFeatureId(2)) || NewLine ||
6574 'GR' || OperatorLetters(OPERATOR_ANYOF) || b_object_name || NewLine;
6575 PACK;
6576 b_object_name := b_object_name || ' ';
6577 END IF;
6578
6579 current_option := -1;
6580 nDebug := 8000010;
6581 FOR a IN (SELECT option_a, option_b FROM TABLE(v_options) ORDER BY option_a) LOOP
6582
6583 IF(a.option_a <> current_option)THEN
6584
6585 IF(current_option <> -1)THEN
6586
6587 --We just moved to the next option. current_option is still the previous option for
6588 --which the generating of the compatible set mask is completed, and the actual mask
6589 --is still in v_mask.
6590 --Here either add the options to an existing compatibility group mask, or create a
6591 --new compatibility group mask.
6592
6593 IF(NOT v_group_by_set_mask_a.EXISTS(v_mask))THEN init_group_mask_a(v_mask); END IF;
6594 set_group_mask_a(v_mask, v_bitpos_a(current_option));
6595 END IF;
6596
6597 current_option := a.option_a;
6598 init_set_mask(v_bitpos_b.COUNT);
6599 END IF;
6600
6601 set_mask(v_bitpos_b(a.option_b));
6602 END LOOP;
6603
6604 --Need to repeat that for the last option.
6605
6606 IF(NOT v_group_by_set_mask_a.EXISTS(v_mask))THEN init_group_mask_a(v_mask); END IF;
6607 set_group_mask_a(v_mask, v_bitpos_a(current_option));
6608
6609 current_option := -1;
6610
6611 FOR b IN (SELECT option_a, option_b FROM TABLE(v_options) ORDER BY option_b) LOOP
6612
6613 IF(b.option_b <> current_option)THEN
6614
6615 IF(current_option <> -1)THEN
6616
6617 IF(NOT v_group_by_set_mask_b.EXISTS(v_mask))THEN init_group_mask_b(v_mask); END IF;
6618 set_group_mask_b(v_mask, v_bitpos_b(current_option));
6619 END IF;
6620
6621 current_option := b.option_b;
6622 init_set_mask(v_bitpos_a.COUNT);
6623 END IF;
6624
6625 set_mask(v_bitpos_a(b.option_a));
6626 END LOOP;
6627
6628 --Need to repeat that for the last option.
6629 nDebug := 8000015;
6630 IF(NOT v_group_by_set_mask_b.EXISTS(v_mask))THEN init_group_mask_b(v_mask); END IF;
6631 set_group_mask_b(v_mask, v_bitpos_b(current_option));
6632
6633 --The tables of compatibility group masks hashed by compatibility set masks have been built
6634 --for both sides. Now we can use them to generate the relations.
6635
6636 v_mask := v_group_by_set_mask_a.FIRST;
6637
6638 WHILE(v_mask IS NOT NULL)LOOP
6639
6640 v_group := v_group_by_set_mask_a(v_mask);
6641 v_rel := 'I';
6642
6643 IF(a_min = 1 AND b_min = 1 AND
6644 v_group_by_set_mask_b.EXISTS(v_group) AND v_group_by_set_mask_b(v_group) = v_mask)THEN
6645
6646 --This is A Implies B, B Implies A. A Requires relation will be generated between v_group and
6647 --v_mask and v_group_by_set_mask_b(v_group) will be deleted so that it will not be processed
6648 --by the cycle on the other side.
6649
6650 v_rel := 'R';
6651 v_group_by_set_mask_b.DELETE(v_group);
6652 END IF;
6653
6654 --Generate an Implies or Requires relation between AnyTrue(v_group) and AnyTrue(v_mask)
6655
6656 vLogicLine := 'GS ' || v_rel || ' ... ' || TO_CHAR(nReasonId) || NewLine || 'GL N '; PACK;
6657
6658 FOR i IN 1..v_bitpos_a.COUNT LOOP
6659 IF(in_group(i))THEN
6660 vLogicLine := GENERATE_NAME(v_BackIndex(1), v_bitinv_a(i)) || ' '; PACK;
6661 END IF;
6662 END LOOP;
6663
6664 vLogicLine := NewLine || 'GR N ' || b_object_name; PACK;
6665 nDebug := 8000020;
6666 FOR i IN 1..v_bitpos_b.COUNT LOOP
6667 IF(in_mask(i))THEN
6668 vLogicLine := GENERATE_NAME(v_BackIndex(2), v_bitinv_b(i)) || ' '; PACK;
6669 END IF;
6670 END LOOP;
6671
6672 vLogicLine := NewLine;
6673 PACK;
6674 v_mask := v_group_by_set_mask_a.NEXT(v_mask);
6675 END LOOP;
6676
6677 v_mask := v_group_by_set_mask_b.FIRST;
6678
6679 WHILE(v_mask IS NOT NULL)LOOP
6680
6681 v_group := v_group_by_set_mask_b(v_mask);
6682 v_rel := 'I';
6683
6684 IF(a_min = 1 AND b_min = 1 AND
6685 v_group_by_set_mask_a.EXISTS(v_group) AND v_group_by_set_mask_a(v_group) = v_mask)THEN
6686
6687 --This is B Implies A, A Implies B. A Requires relation will be generated between v_group and
6688 --v_mask. We don't need to delete anything from the other side.
6689
6690 v_rel := 'R';
6691 END IF;
6692
6693 --Generate an Implies or Requires relation between AnyTrue(v_group) and AnyTrue(v_mask)
6694
6695 vLogicLine := 'GS ' || v_rel || ' ... ' || TO_CHAR(nReasonId) || NewLine || 'GL N '; PACK;
6696 nDebug := 8000025;
6697 FOR i IN 1..v_bitpos_b.COUNT LOOP
6698 IF(in_group(i))THEN
6699 vLogicLine := GENERATE_NAME(v_BackIndex(2), v_bitinv_b(i)) || ' '; PACK;
6700 END IF;
6701 END LOOP;
6702
6703 vLogicLine := NewLine || 'GR N ' || a_object_name; PACK;
6704
6705 FOR i IN 1..v_bitpos_a.COUNT LOOP
6706 IF(in_mask(i))THEN
6707 vLogicLine := GENERATE_NAME(v_BackIndex(1), v_bitinv_a(i)) || ' '; PACK;
6708 END IF;
6709 END LOOP;
6710
6711 vLogicLine := NewLine;
6712 PACK;
6713 v_mask := v_group_by_set_mask_b.NEXT(v_mask);
6714 END LOOP;
6715
6716 -- The following block can be optimized by splitting into two (for a and b), and
6717 -- 1) using featOptionsCount table and compare it to v_bitpos_a(b).COUNT to find out if excludes
6718 -- are required instead of cycling through the feature options;
6719 -- 2) using v_bitpos_a(b) instead of v_OptionExists thus avoiding populating this table.
6720
6721 v_OptionExists.DELETE;
6722
6723 --Hash all the options of both features that are compatible. If an option is not in the hash,
6724 --exclude relation will be generated later.
6725 nDebug := 8000030;
6726 FOR i IN 1..v_options.COUNT LOOP
6727 v_OptionExists(v_options(i).option_a) := 1;
6728 v_OptionExists(v_options(i).option_b) := 1;
6729 END LOOP;
6730
6731 --Generate the exclude relations if necessary.
6732 --The code is re-written as part of the fix for the bug #4546828 to use the new hash table.
6733
6734 FOR i IN 1..v_tFeatureId.COUNT LOOP
6735
6736 ExcludesRequired := 0;
6737 nChild := h_OptionExplId(i).FIRST;
6738 nCounter := nChild;
6739
6740 WHILE(nChild IS NOT NULL) LOOP
6741 IF(NOT v_OptionExists.EXISTS(nChild))THEN
6742 ExcludesRequired := 1;
6743 EXIT;
6744 END IF;
6745 nChild := h_OptionExplId(i).NEXT(nChild);
6746 END LOOP;
6747
6748 IF(ExcludesRequired = 1)THEN
6749
6750 nChild := nCounter;
6751 nDebug := 8000040;
6752 vLogicLine := 'GS E ... ' || TO_CHAR(nReasonId) || NewLine || 'GL N ';
6753 PACK;
6754
6755 WHILE(nChild IS NOT NULL) LOOP
6756 IF(NOT v_OptionExists.EXISTS(nChild))THEN
6757 vLogicLine := GENERATE_NAME_EXPL(h_OptionExplId(i)(nChild), nChild) || ' ';
6758 PACK;
6759 END IF;
6760 nChild := h_OptionExplId(i).NEXT(nChild);
6761 END LOOP;
6762
6763 vLogicLine := NewLine || 'GR L ';
6764 PACK;
6765
6766 FOR n IN 1..v_tFeatureId.COUNT LOOP
6767 IF(n <> i)THEN
6768 vLogicLine := GENERATE_NAME(v_BackIndex(n), v_tFeatureId(n)) || ' ';
6769 PACK;
6770 END IF;
6771 END LOOP;
6772
6773 vLogicLine := NewLine;
6774 PACK;
6775 END IF; --Excludes required
6776 END LOOP;
6777 END GENERATE_OPTIMIZED_PBC;
6778 ---------------------------------------------------------------------------------------
6779 BEGIN
6780
6781 --High-level property-based compatibility rule validation section
6782 --Make sure the rule has at least 2 participant features
6783
6784 IF(participantCount < 2)THEN
6785 RAISE CZ_R_COMPAT_SINGLE_FEATURE;
6786 END IF;
6787
6788 nDebug := 7005100;
6789
6790 nChild := v_ChildrenIndex(v_tExprId(j));
6791 nCounter := 1;
6792
6793 WHILE(v_tExprParentId(nChild) = v_tExprId(j)) LOOP
6794 IF(v_tExprType(nChild) = EXPR_ITERATOR)THEN
6795
6796 iteratorIndex(nCounter) := nChild;
6797 featureIndex := v_ChildrenIndex(v_tExprId(nChild));
6798
6799 v_tFeatureId(nCounter) := v_tExprPsNodeId(featureIndex);
6800 v_tExplId(nCounter) := v_tExplNodeId(featureIndex);
6801 v_BackIndex(nCounter) := featureIndex;
6802
6803 nCounter := nCounter + 1;
6804
6805 ELSIF(v_tExprType(nChild) = EXPR_WHERE)THEN
6806
6807 whereIndex := nChild;
6808 END IF;
6809
6810 nChild := nChild + 1;
6811 END LOOP;
6812
6813 nDebug := 7005101;
6814
6815 FOR i IN 1..iteratorIndex.COUNT LOOP
6816
6817 bind_node_id.DELETE;
6818 bind_values.DELETE;
6819
6820 v_property_id.DELETE;
6821 v_data_type.DELETE;
6822 v_prop_name.DELETE;
6823 v_flag.DELETE;
6824
6825 temp_cmpt_hash_key(compatLevel) := NULL;
6826 tableAlias := 'C' || TO_CHAR(i);
6827
6828 iterator.DELETE;
6829 iterator := GENERATE_ITERATOR(iteratorIndex(i), ListType);
6830
6831 IF(whereIndex <> 0)THEN
6832 EXPLORE_WHERE(whereIndex, v_tExprArgumentName(iteratorIndex(i)));
6833 END IF;
6834
6835 IF(temp_cmpt_hash_key(compatLevel) IS NOT NULL)THEN
6836 FOR ii IN 1..v_property_id.COUNT LOOP
6837 temp_cmpt_hash_key(compatLevel) := temp_cmpt_hash_key(compatLevel) || '-' || TO_CHAR(v_property_id(ii));
6838 END LOOP;
6839 END IF;
6840
6841 nDebug := 7005102;
6842
6843 IF(temp_cmpt_hash_key(compatLevel) IS NOT NULL AND temp_cmpt_table_hash.EXISTS(temp_cmpt_hash_key(compatLevel)))THEN
6844
6845 tableName := temp_cmpt_table_hash(temp_cmpt_hash_key(compatLevel));
6846 arg_table_name(v_tExprArgumentName(iteratorIndex(i))) := tableAlias;
6847
6848 IF(SQLSelect IS NULL)THEN SQLSelect := 'SELECT '; ELSE SQLSelect := SQLSelect || ', '; END IF;
6849 SQLSelect := SQLSelect || tableAlias || '.node_id';
6850 IF(SQLFrom IS NULL)THEN SQLFrom := ' FROM '; ELSE SQLFrom := SQLFrom || ', '; END IF;
6851 SQLFrom := SQLFrom || tableName || ' ' || tableAlias;
6852
6853 FOR ii IN 1..iterator.COUNT LOOP
6854 h_OptionExplId(i)(iterator(ii).node_id) := iterator(ii).node_id_ex;
6855 END LOOP;
6856 ELSE
6857
6858 --tableName := 'G_' || TO_CHAR(table_name_generator);
6859 -- SMANNA : Bug11822849 : Want to make these global temp table name unique between the sessions.
6860 tableName := 'G_' ||TO_CHAR(thisRunId)||'_'|| TO_CHAR(table_name_generator);
6861 table_name_generator := table_name_generator + 1;
6862 arg_table_name(v_tExprArgumentName(iteratorIndex(i))) := tableAlias;
6863
6864 IF(SQLSelect IS NULL)THEN SQLSelect := 'SELECT '; ELSE SQLSelect := SQLSelect || ', '; END IF;
6865 SQLSelect := SQLSelect || tableAlias || '.node_id';
6866 IF(SQLFrom IS NULL)THEN SQLFrom := ' FROM '; ELSE SQLFrom := SQLFrom || ', '; END IF;
6867 SQLFrom := SQLFrom || tableName || ' ' || tableAlias;
6868
6869 SQLCreate := 'CREATE GLOBAL TEMPORARY TABLE ' || tableName || '(node_id NUMBER ';
6870
6871 FOR ii IN 1..v_property_id.COUNT LOOP
6872
6873 SQLCreate := SQLCreate || ', i_' || TO_CHAR(v_property_id(ii));
6874
6875 IF(v_data_type(ii) IN (DATA_TYPE_INTEGER, DATA_TYPE_DECIMAL))THEN
6876
6877 SQLCreate := SQLCreate || ' NUMBER';
6878 ELSE
6879
6880 SQLCreate := SQLCreate || ' VARCHAR2(' || TO_CHAR(MAXIMUM_INDEX_LENGTH) || ')';
6881 END IF;
6882 END LOOP;
6883
6884 SQLCreate := SQLCreate || ') ON COMMIT PRESERVE ROWS';
6885
6886 nDebug := 7005103;
6887
6888 BEGIN
6889 EXECUTE IMMEDIATE SQLCreate;
6890 EXCEPTION
6891 WHEN OTHERS THEN
6892
6893 --If the table already exists, truncate it, drop and try to create again.
6894
6895 IF(SQLCODE = ORACLE_OBJECT_ALREADY_EXISTS)THEN
6896 EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || tableName;
6897 EXECUTE IMMEDIATE 'DROP TABLE ' || tableName;
6898 EXECUTE IMMEDIATE SQLCreate;
6899 ELSE
6900 RAISE;
6901 END IF;
6902 END;
6903
6904 --The table is created, add its name to the delete list.
6905
6906 temp_tables(temp_tables.COUNT + 1) := tableName;
6907
6908 nDebug := 7005104;
6909
6910 SQLInsert := 'INSERT INTO ' || tableName || '(node_id';
6911 SQLValues := ' VALUES (:y1';
6912
6913 FOR ii IN 1..v_property_id.COUNT LOOP
6914
6915 BEGIN
6916
6917 EXECUTE IMMEDIATE 'CREATE INDEX ' || tableName || '_I' || TO_CHAR(ii) || ' ON ' || tableName ||
6918 '(i_' || v_property_id(ii) || ')';
6919 EXCEPTION
6920 WHEN OTHERS THEN
6921 IF(SQLCODE <> ORACLE_OBJECT_ALREADY_EXISTS)THEN RAISE; END IF;
6922 END;
6923
6924 SQLInsert := SQLInsert || ', i_' || TO_CHAR(v_property_id(ii));
6925 SQLValues := SQLValues || ', :x' || TO_CHAR(ii);
6926 END LOOP;
6927
6928 SQLInsert := SQLInsert || ')';
6929 SQLValues := SQLValues || ')';
6930
6931 nDebug := 7005105;
6932
6933 FOR ii IN 1..iterator.COUNT LOOP
6934
6935 bind_node_id(ii) := iterator(ii).node_id;
6936
6937 IF(v_property_id.COUNT > 0)THEN
6938
6939 --This is only valid if there are properties.
6940
6941 IF(iterator(ii).node_id IS NULL)THEN RAISE CZ_R_TYPE_NO_PROPERTY; END IF;
6942
6943 nodeId := glPsNodeId(glIndexByPsNodeId(iterator(ii).node_id));
6944 itemId := glItemId(glIndexByPsNodeId(iterator(ii).node_id));
6945 END IF;
6946
6947 --Get the property values and insert the data.
6948
6949 nDebug := 7005106;
6950
6951 FOR jj IN 1..v_property_id.COUNT LOOP
6952
6953 propertyId := v_property_id(jj);
6954 hash_propval_key := TO_CHAR(nodeId) || '-' || TO_CHAR(itemId) || '-' ||
6955 TO_CHAR(propertyId) || '-' || TO_CHAR(v_flag(propertyId));
6956
6957 IF(NOT table_hash_propval.EXISTS(hash_propval_key))THEN
6958
6959 IF(v_flag(propertyId) = 0)THEN
6960
6961 --User property.
6962
6963 propertyVal := NULL;
6964 localNumber := NULL;
6965 propertyVal := GET_PROPERTY_VALUE(nodeId, propertyId, itemId, localNumber);
6966 ELSE
6967
6968 --System property.
6969
6970 localNumber := 1;
6971 propertyVal := STATIC_SYSPROP_VALUE(nodeId, propertyId, v_flag(v_property_id(jj)));
6972 END IF;
6973
6974 --Bug #3829438. Second and third columns of the cursor are not null, so localNumber can be NULL
6975 --only if no rows are fetched.
6976
6977 IF(localNumber IS NOT NULL)THEN
6978 IF(v_data_type(jj) IN (DATATYPE_INTEGER, DATATYPE_FLOAT))THEN
6979
6980 --If the property has numeric type, but the data is corrupted and the value
6981 --cannot be actually converted to a number, the generated SQL statement may
6982 --produce incomprehensive syntax errors, like 'too many columns'. To avoid
6983 --this verify the value.
6984
6985 BEGIN
6986 typeCheck := TO_NUMBER(propertyVal);
6987 EXCEPTION
6988 WHEN OTHERS THEN
6989 errorMessage := v_prop_name(jj);
6990 localString := propertyVal;
6991 RAISE CZ_R_INCORRECT_DATA_TYPE;
6992 END;
6993 ELSIF(LENGTH(propertyVal) > MAXIMUM_INDEX_LENGTH)THEN
6994
6995 errorMessage := v_prop_name(jj);
6996 nParam := glIndexByPsNodeId(v_tFeatureId(i));
6997 auxIndex := glIndexByPsNodeId(iterator(ii).node_id);
6998 RAISE CZ_R_LONG_PROPERTY_VALUE;
6999 END IF;
7000 ELSE
7001 errorMessage := v_prop_name(jj);
7002 nParam := glIndexByPsNodeId(v_tFeatureId(i));
7003 auxIndex := glIndexByPsNodeId(iterator(ii).node_id);
7004 RAISE CZ_R_OPTION_NO_PROPERTY;
7005 END IF;
7006
7007 bind_values(jj)(ii) := propertyVal;
7008 table_hash_propval(hash_propval_key) := propertyVal;
7009 ELSE
7010 bind_values(jj)(ii) := table_hash_propval(hash_propval_key);
7011 END IF;
7012 END LOOP;
7013
7014 --Bug #4546828.
7015 --In a BOM model, options can really be references to other BOM models, therefore each option
7016 --can have its own explosion id, which should be used to generate correct logic name.
7017 --Hash the explosion id(s) here in a two-dimensional table (iterator, option_id).
7018 --Here we are supposed to hash all eligible options of the parent (the eligibility determined
7019 --by EXPAND_NODE inside the GENERATE_ITERATOR). For example, if a BOM model has BOM standard
7020 --items and a non-BOM feature, only the bom items are eligible. Therefore, this table will be
7021 --used later when generating exclusions.
7022
7023 h_OptionExplId(i)(nodeId) := iterator(ii).node_id_ex;
7024 END LOOP;
7025
7026 nDebug := 7005107;
7027
7028 v_cursor := DBMS_SQL.OPEN_CURSOR;
7029 DBMS_SQL.PARSE(v_cursor, SQLInsert || SQLValues, DBMS_SQL.NATIVE);
7030
7031 DBMS_SQL.BIND_ARRAY(v_cursor, ':y1', bind_node_id);
7032
7033 FOR ii IN 1..v_property_id.COUNT LOOP
7034 DBMS_SQL.BIND_ARRAY(v_cursor, ':x' || TO_CHAR(ii), bind_values(ii));
7035 END LOOP;
7036
7037 localNumber := DBMS_SQL.EXECUTE(v_cursor);
7038 DBMS_SQL.CLOSE_CURSOR(v_cursor);
7039
7040 EXECUTE IMMEDIATE 'ANALYZE TABLE ' || tableName || ' COMPUTE STATISTICS';
7041
7042 --The table is created and populated, add its name to the hash for re-use if it is eligible.
7043
7044 IF(temp_cmpt_hash_key(compatLevel) IS NOT NULL)THEN temp_cmpt_table_hash(temp_cmpt_hash_key(compatLevel)) := tableName; END IF;
7045 END IF;
7046 END LOOP;
7047
7048 --Generate the WHERE clause and run the query with bind variables. For every row returned,
7049 --generate the expression and return the object.
7050 --To do this, add GENERATE_ARGUMENT to the GENERATE_EXPRESSION.
7051
7052 nDebug := 7005108;
7053
7054 IF(whereIndex <> 0)THEN
7055 SQLWhere := ' WHERE ' || EXAMINE_WHERE_CLAUSE(v_ChildrenIndex(v_tExprId(whereIndex)));
7056 END IF;
7057
7058 IF(v_tFeatureId.COUNT = 2)THEN
7059 GENERATE_OPTIMIZED_PBC;
7060 ELSE
7061
7062 GENERATE_STANDARD_PBC;
7063 END IF;
7064
7065 RETURN v_return;
7066 END;
7067 ---------------------------------------------------------------------------------------
7068 --This function is introduced to support the level of embedding.
7069
7070 FUNCTION GENERATE_COMPATIBLE(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
7071 v_return tStringArray;
7072 BEGIN
7073 compatLevel := compatLevel + 1;
7074 v_return := GENERATE_COMPATIBLE_(j, ListType);
7075 compatLevel := compatLevel - 1;
7076 RETURN v_return;
7077 EXCEPTION
7078 WHEN OTHERS THEN
7079 compatLevel := compatLevel - 1;
7080 RAISE;
7081 END;
7082 ---------------------------------------------------------------------------------------
7083 FUNCTION GENERATE_EXPRESSION(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
7084 v_return tStringArray;
7085 v_result tIteratorArray;
7086 BEGIN
7087
7088 ListType := DATATYPE_GENERIC;
7089
7090 IF(v_tExprType(j) = EXPR_NODE_TYPE_NODE)THEN
7091
7092 IF(v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
7093
7094 RETURN GENERATE_REFNODE(j, ListType);
7095 ELSE
7096
7097 RETURN GENERATE_NODE(j);
7098 END IF;
7099
7100 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_FEATPROP)THEN
7101
7102 RETURN GENERATE_PROPERTY(j);
7103
7104 ELSIF(v_tExprType(j) = EXPR_PROP)THEN
7105
7106 v_return(1) := PROPERTY_VALUE(j, glIndexByPsNodeId(v_tExprPsNodeId(j - 1)), ListType);
7107
7108 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_OPERATOR)THEN
7109
7110 IF(v_tExprSubtype(j) IN (OPERATOR_ADD,
7111 OPERATOR_SUB,
7112 OPERATOR_MULT,
7113 OPERATOR_DIV,
7114 OPERATOR_ADD_INT,
7115 OPERATOR_SUB_INT,
7116 OPERATOR_MULT_INT))THEN
7117 RETURN GENERATE_ARITHMETIC(j);
7118
7119 ELSIF(v_tExprSubtype(j) IN (OPERATOR_COS,
7120 OPERATOR_ACOS,
7121 OPERATOR_COSH,
7122 OPERATOR_SIN,
7123 OPERATOR_ASIN,
7124 OPERATOR_SINH,
7125 OPERATOR_TAN,
7126 OPERATOR_ATAN,
7127 OPERATOR_TANH,
7128 OPERATOR_LOG,
7129 OPERATOR_LOG10,
7130 OPERATOR_EXP,
7131 OPERATOR_ABS,
7132 OPERATOR_SQRT))THEN
7133 RETURN GENERATE_MATH_UNARY(j);
7134
7135 ELSIF(v_tExprSubtype(j) IN (OPERATOR_MATHDIV,
7136 OPERATOR_POW,
7137 OPERATOR_POW_INT,
7138 OPERATOR_ATAN2,
7139 OPERATOR_MOD))THEN
7140 RETURN GENERATE_MATH_BINARY(j);
7141
7142 ELSIF(v_tExprSubtype(j) IN (OPERATOR_ROUNDTONEAREST,
7143 OPERATOR_ROUNDUPTONEAREST,
7144 OPERATOR_ROUNDDOWNTONEAREST))THEN
7145 RETURN GENERATE_MATH_ROUND(j);
7146
7147 ELSIF(v_tExprSubtype(j) IN (OPERATOR_CEILING,
7148 OPERATOR_FLOOR,
7149 OPERATOR_ROUND,
7150 OPERATOR_TRUNCATE))THEN
7151 RETURN GENERATE_ROUND(j);
7152
7153 ELSIF(v_tExprSubtype(j) IN (OPERATOR_AND,
7154 OPERATOR_OR))THEN
7155 RETURN GENERATE_ANDOR(j, ListType);
7156
7157 ELSIF(v_tExprSubtype(j) IN (OPERATOR_ANYOF,
7158 OPERATOR_ALLOF))THEN
7159 RETURN GENERATE_ANYALLOF(j, ListType);
7160
7161 ELSIF(v_tExprSubtype(j) = OPERATOR_NOT)THEN
7162 RETURN GENERATE_NOT(j);
7163
7164 ELSIF(v_tExprSubtype(j) = OPERATOR_NOTTRUE)THEN
7165 RETURN GENERATE_NOTTRUE(j);
7166
7167 ELSIF(v_tExprSubtype(j) IN (OPERATOR_EQUALS,
7168 OPERATOR_NOTEQUALS,
7169 OPERATOR_GT,
7170 OPERATOR_LT,
7171 OPERATOR_GE,
7172 OPERATOR_LE,
7173 OPERATOR_EQUALS_INT,
7174 OPERATOR_NOTEQUALS_INT,
7175 OPERATOR_GT_INT,
7176 OPERATOR_LT_INT,
7177 OPERATOR_GE_INT,
7178 OPERATOR_LE_INT,
7179 OPERATOR_BEGINSWITH,
7180 OPERATOR_ENDSWITH,
7181 OPERATOR_CONTAINS,
7182 OPERATOR_LIKE,
7183 OPERATOR_MATCHES,
7184 OPERATOR_DOESNOTBEGINWITH,
7185 OPERATOR_DOESNOTENDWITH,
7186 OPERATOR_DOESNOTCONTAIN,
7187 OPERATOR_NOTLIKE))THEN
7188 RETURN GENERATE_COMPARE(j);
7189
7190 ELSIF(v_tExprSubtype(j) = OPERATOR_CONCAT)THEN
7191 RETURN GENERATE_CONCAT(j, ListType);
7192
7193 ELSIF(v_tExprSubtype(j) = OPERATOR_TOTEXT)THEN
7194
7195 --Bug 5620750 - recognize and handle the new ToText operator when used outside of PBC
7196 --context.
7197
7198 RETURN GENERATE_TOTEXT(j, ListType);
7199
7200 ELSIF(v_tExprSubtype(j) IN (OPERATOR_OPTIONSOF, OPERATOR_BOMOPTIONSOF))THEN
7201 RETURN GENERATE_OF(j);
7202
7203 ELSIF(v_tExprSubtype(j) IN (OPERATOR_MIN,
7204 OPERATOR_MAX))THEN
7205 RETURN GENERATE_MINMAX(j);
7206
7207 ELSIF(v_tExprSubtype(j) IN (OPERATOR_VAL))THEN
7208 RETURN GENERATE_VAL(j);
7209
7210 ELSIF(v_tExprSubtype(j) IN (RULE_OPERATOR_REQUIRES,
7211 RULE_OPERATOR_IMPLIES,
7212 RULE_OPERATOR_EXCLUDES,
7213 RULE_OPERATOR_NEGATES,
7214 RULE_OPERATOR_DEFAULTS))THEN
7215 RETURN GENERATE_LOGIC_TREE(j);
7216
7217 ELSIF(v_tExprSubtype(j) IN (RULE_OPERATOR_CONTRIBUTES,
7218 RULE_OPERATOR_CONSUMES))THEN
7219 RETURN GENERATE_NUMERIC_TREE(j);
7220
7221 ELSE
7222
7223 --This is not a built-in operator (primitive template), so generate it as a template application.
7224 --Right now there is no reason to report it as unknown.
7225
7226 RETURN GENERATE_TEMPLATE_APPLICATION (j, ListType);
7227
7228 --nParam := v_tExprSubtype(j);
7229 --RAISE CZ_E_UNKNOWN_OPERATOR_TYPE;
7230 END IF;
7231
7232 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_LITERAL)THEN
7233
7234 RETURN GENERATE_LITERAL(j);
7235
7236 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_CONSTANT)THEN
7237
7238 RETURN GENERATE_CONSTANT(j);
7239
7240 ELSIF(v_tExprType(j) IN (EXPR_FORALL, EXPR_FORALL_DISTINCT))THEN
7241
7242 v_result := GENERATE_FORALL(j, ListType);
7243
7244 FOR i IN 1..v_result.COUNT LOOP
7245 v_return(i) := v_result(i).node_obj;
7246 IF(v_return(i) IS NULL AND v_result(i).node_id IS NOT NULL AND v_result(i).node_id_ex IS NOT NULL)THEN
7247 v_return(i) := GENERATE_NAME_EXPL(v_result(i).node_id_ex, v_result(i).node_id);
7248 END IF;
7249 END LOOP;
7250
7251 ELSIF(v_tExprType(j) = EXPR_COMPATIBLE)THEN
7252
7253 RETURN GENERATE_COMPATIBLE(j, ListType);
7254
7255 ELSIF(v_tExprType(j) = EXPR_ARGUMENT)THEN
7256
7257 IF(v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
7258
7259 RETURN GENERATE_REFNODE(j, ListType);
7260 ELSE
7261
7262 ListType := DATA_TYPE_VOID;
7263 RETURN GENERATE_ARGUMENT(j, ListType);
7264 END IF;
7265
7266 ELSE
7267
7268 RAISE CZ_E_UNKNOWN_EXPR_TYPE;
7269 END IF;
7270 RETURN v_return;
7271 END;
7272 ---------------------------------------------------------------------------------------
7273 PROCEDURE GENERATE_COMPATIBILITY_TABLE IS
7274 v_tOptionId tOptionId;
7275 v_OptionExists tIntegerArray_idx_vc2; --kdande; Bug 6881902; 11-Mar-2008
7276 v_RowLines tStringArray;
7277 v_ItemLines tStringArray;
7278 itemIndex PLS_INTEGER;
7279 itemCount PLS_INTEGER := 1;
7280 nChild PLS_INTEGER;
7281 nCounter PLS_INTEGER;
7282 ExcludesRequired PLS_INTEGER;
7283 PrimaryCount PLS_INTEGER;
7284 localString VARCHAR2(25);
7285 localNumber PLS_INTEGER;
7286 BEGIN
7287
7288 nDebug := 5000001;
7289
7290 FOR i IN 1..v_tExprPsNodeId.COUNT LOOP
7291
7292 v_tOptionId.DELETE;
7293 v_OptionExists.DELETE;
7294
7295 nDebug := 5000002;
7296
7297 SELECT secondary_opt_id BULK COLLECT INTO v_tOptionId
7298 FROM cz_des_chart_cells
7299 WHERE deleted_flag = FLAG_NOT_DELETED
7300 AND rule_id = nRuleId
7301 AND secondary_feature_id = v_tExprPsNodeId(i)
7302 AND secondary_feat_expl_id = v_tExplNodeId(i);
7303
7304 IF(v_tOptionId.COUNT = 0)THEN
7305 RAISE CZ_R_EMPTY_COMPAT_RULE;
7306 ELSIF(i = 1)THEN
7307 PrimaryCount := v_tOptionId.COUNT;
7308 ELSE
7309 IF(v_tOptionId.COUNT <> PrimaryCount)THEN
7310 RAISE CZ_R_WRONG_COMPAT_TABLE;
7311 END IF;
7312 END IF;
7313
7314 nDebug := 5000003;
7315
7316 FOR n IN 1..v_tOptionId.COUNT LOOP
7317
7318 --Make sure the option exists
7319
7320 IF(NOT glIndexByPsNodeId.EXISTS(v_tOptionId(n)))THEN
7321 RAISE CZ_R_INCORRECT_NODE_ID;
7322 END IF;
7323
7324 IF(NOT v_OptionExists.EXISTS(v_tOptionId(n)))THEN
7325
7326 nDebug := 5000004;
7327
7328 v_ItemLines(itemCount) := GENERATE_NAME(i, v_tOptionId(n)) || ' ' || TO_CHAR(i - 1);
7329 v_OptionExists(v_tOptionId(n)) := itemCount;
7330 itemCount := itemCount + 1;
7331
7332 END IF;
7333
7334 nDebug := 5000005;
7335
7336 itemIndex := v_OptionExists(v_tOptionId(n));
7337
7338 IF(v_RowLines.EXISTS(n))THEN
7339 v_RowLines(n) := v_RowLines(n) || ' ' || TO_CHAR(itemIndex - 1);
7340 ELSE
7341 v_RowLines(n) := ' ' || TO_CHAR(itemIndex - 1);
7342 END IF;
7343
7344 END LOOP;
7345
7346 nDebug := 5000006;
7347
7348 nChild := glIndexByPsNodeId(v_tExprPsNodeId(i)) + 1;
7349 nCounter := nChild;
7350 ExcludesRequired := 0;
7351
7352 nDebug := 5000007;
7353
7354 WHILE(glParentId.EXISTS(nChild) AND glParentId(nChild) = v_tExprPsNodeId(i))LOOP
7355 IF(NOT v_OptionExists.EXISTS(glPsNodeId(nChild)))THEN
7356 ExcludesRequired := 1;
7357 EXIT;
7358 END IF;
7359 nChild := nChild + 1;
7360 END LOOP;
7361
7362 nDebug := 5000008;
7363
7364 IF(ExcludesRequired = 1)THEN
7365
7366 nChild := nCounter;
7367
7368 vLogicLine := 'GS E ... ' || TO_CHAR(nReasonId) || NewLine || 'GL N ';
7369 PACK;
7370
7371 WHILE(glParentId.EXISTS(nChild) AND glParentId(nChild) = v_tExprPsNodeId(i))LOOP
7372 IF(NOT v_OptionExists.EXISTS(glPsNodeId(nChild)))THEN
7373 vLogicLine := GENERATE_NAME(i, glPsNodeId(nChild)) || ' ';
7374 PACK;
7375 END IF;
7376 nChild := nChild + 1;
7377 END LOOP;
7378
7379 nDebug := 5000009;
7380
7381 vLogicLine := NewLine || 'GR L ';
7382 PACK;
7383
7384 FOR n IN 1..v_tExprPsNodeId.COUNT LOOP
7385 IF(n <> i)THEN
7386 vLogicLine := GENERATE_NAME(n, v_tExprPsNodeId(n)) || ' ';
7387 PACK;
7388 END IF;
7389 END LOOP;
7390
7391 nDebug := 5000010;
7392
7393 vLogicLine := NewLine;
7394 PACK;
7395 END IF; --Excludes required
7396 END LOOP;
7397
7398 nDebug := 5000011;
7399
7400 vLogicLine := 'OBJECT P_R' || TO_CHAR(nRuleId) || NewLine ||
7401 'COMBO P_R' || TO_CHAR(nRuleId) || ' ' || TO_CHAR(v_ItemLines.COUNT) || ' ' ||
7402 TO_CHAR(v_RowLines.COUNT) || ' ' || TO_CHAR(v_tExprPsNodeId.COUNT) || ' ... ' ||
7403 TO_CHAR(nReasonId) || NewLine;
7404 PACK;
7405
7406 nDebug := 5000012;
7407
7408 FOR i IN 1..v_ItemLines.COUNT LOOP
7409
7410 vLogicLine := 'CI ' || TO_CHAR(i - 1) || ' ' || v_ItemLines(i) || NewLine;
7411 PACK;
7412
7413 END LOOP;
7414
7415 nDebug := 5000013;
7416
7417 FOR i IN 1..v_tExprPsNodeId.COUNT LOOP
7418
7419 IF(GenerateGatedCombo = 0)THEN
7420
7421 --Use intermediate variable instead of using NVL because this is faster
7422
7423 localNumber := glIndexByPsNodeId(v_tExprPsNodeId(i));
7424 localString := TO_CHAR(glMaximum(localNumber));
7425
7426 --If it's a BOM item, we use maximum_selected instead of maximum
7427
7428 IF(glPsNodeType(localNumber) IN (PS_NODE_TYPE_BOM_MODEL,PS_NODE_TYPE_BOM_OPTIONCLASS,PS_NODE_TYPE_BOM_STANDARD))THEN
7429 localString := TO_CHAR(glMaximumSel(localNumber));
7430 END IF;
7431
7432 IF(localString IS NULL)THEN localString := '-1'; END IF;
7433 vLogicLine := ' O';
7434 ELSE
7435
7436 --Generate gated combinations: maximum is always -1, the 'G' argument is followed
7437 --by the feature name.
7438
7439 localString := '-1';
7440 vLogicLine := ' G ' || GENERATE_NAME(i, v_tExprPsNodeId(i));
7441 END IF;
7442
7443 vLogicLine := 'CC ' || TO_CHAR(i - 1) || ' 0 ' || localString || vLogicLine || NewLine;
7444 PACK;
7445
7446 END LOOP;
7447
7448 nDebug := 5000014;
7449
7450 FOR i IN 1..v_RowLines.COUNT LOOP
7451
7452 vLogicLine := 'CR ' || TO_CHAR(i - 1) || v_RowLines(i) || NewLine;
7453 PACK;
7454
7455 END LOOP;
7456
7457 nDebug := 5000015;
7458
7459 vLogicLine := 'COMBO_END' || NewLine;
7460 PACK;
7461
7462 END;
7463 ---------------------------------------------------------------------------------------
7464 PROCEDURE GENERATE_DESIGNCHART_RULE IS
7465 vGridColumns tPsNodeId;
7466 vBackIndex tIntegerArray;
7467 nIndex PLS_INTEGER;
7468 ---------------------------------------------------------------------------------------
7469 PROCEDURE GENERATE_COMPAT_TEMPLATE(inSuffix IN PLS_INTEGER) IS
7470 v_tOptionId tOptionId;
7471 v_tPrimaryOptId tOptionId;
7472 v_tPrimaryId tOptionId;
7473 v_OptionExists tIntegerArray_idx_vc2; --kdande; Bug 6881902; 11-Mar-2008
7474 v_OptionsUsed tIntegerArray;
7475 v_StartOptionsUsed tIntegerArray;
7476 v_EndOptionsUsed tIntegerArray;
7477 v_ExcludesRequired tIntegerArray;
7478 v_RowLinesIndex tIntegerArray;
7479 v_RowLines tStringArray;
7480 v_tailRowLines tStringArray;
7481 v_ItemLines tStringArray;
7482 itemIndex PLS_INTEGER;
7483 itemCount PLS_INTEGER := 1;
7484 startCount PLS_INTEGER;
7485 nChild PLS_INTEGER;
7486 localString VARCHAR2(25);
7487 localNumber PLS_INTEGER;
7488 ---------------------------------------------------------------------------------------
7489 FUNCTION OPTION_EXISTS(nIndex IN PLS_INTEGER) RETURN PLS_INTEGER IS
7490 BEGIN
7491 FOR j IN v_StartOptionsUsed(nIndex)..v_EndOptionsUsed(nIndex) LOOP
7492 IF(v_OptionsUsed(j) = glPsNodeId(nChild))THEN RETURN 1; END IF;
7493 END LOOP;
7494 RETURN 0;
7495 END;
7496 ---------------------------------------------------------------------------------------
7497 --This procedure implements a version of QuickSort algorythm which sorts not the array
7498 --itself, but the array of pointers instead
7499
7500 PROCEDURE SORT_ARRAY_INDEX(indexStart IN PLS_INTEGER, indexEnd IN PLS_INTEGER) IS
7501 localStart PLS_INTEGER;
7502 localEnd PLS_INTEGER;
7503 localSwap PLS_INTEGER;
7504 RowLine VARCHAR2(4000);
7505 BEGIN
7506
7507 IF(indexStart >= indexEnd)THEN RETURN; END IF;
7508
7509 localStart := indexStart;
7510 localEnd := indexEnd;
7511 RowLine := v_tailRowLines(v_RowLinesIndex((localStart + localEnd) / 2));
7512
7513 WHILE(localStart < localEnd)LOOP
7514
7515 WHILE(localStart < localEnd AND v_tailRowLines(v_RowLinesIndex(localStart)) < RowLine) LOOP
7516 localStart := localStart + 1;
7517 END LOOP;
7518
7519 WHILE(localStart < localEnd AND v_tailRowLines(v_RowLinesIndex(localEnd)) > RowLine) LOOP
7520 localEnd := localEnd - 1;
7521 END LOOP;
7522
7523 IF(localStart < localEnd)THEN
7524 localSwap := v_RowLinesIndex(localStart);
7525 v_RowLinesIndex(localStart) := v_RowLinesIndex(localEnd);
7526 v_RowLinesIndex(localEnd) := localSwap;
7527 END IF;
7528
7529 localStart := localStart + 1;
7530 localEnd := localEnd - 1;
7531
7532 END LOOP;
7533
7534 IF(localEnd < localStart)THEN
7535 localSwap := localEnd;
7536 localEnd := localStart;
7537 localStart := localSwap;
7538 END IF;
7539
7540 SORT_ARRAY_INDEX(indexStart, localStart);
7541 IF(localStart = indexStart)THEN localStart := localStart + 1; END IF;
7542 SORT_ARRAY_INDEX(localStart, indexEnd);
7543 END;
7544 ---------------------------------------------------------------------------------------
7545 BEGIN
7546
7547 nDebug := 5000200;
7548
7549 FOR i IN 1..vGridColumns.COUNT LOOP --Validation and initial data for features
7550
7551 nDebug := 5000201;
7552
7553 IF(i = 1)THEN
7554
7555 --Read the list of participating options of the primary feature. Make a copy of the list
7556 --for the rule verification purposes (bug #2257421).
7557
7558 SELECT primary_opt_id, primary_opt_id BULK COLLECT INTO v_tOptionId, v_tPrimaryOptId
7559 FROM cz_des_chart_cells
7560 WHERE rule_id = nRuleId
7561 AND secondary_feature_id = vGridColumns(2)
7562 AND secondary_feat_expl_id = v_tExplNodeId(vBackIndex(2))
7563 AND deleted_flag = FLAG_NOT_DELETED
7564 ORDER BY 1, 2;
7565
7566 IF(v_tOptionId.COUNT = 0)THEN
7567
7568 --The previous query returned no rows. That means that there're no selections made for
7569 --any of the primary feature options. It's OK if we are processing an optional table,
7570 --but for the defining table we raise an exception.
7571
7572 IF(inSuffix = 0)THEN --we are processing the defining table
7573 RAISE CZ_R_NO_DEFINING_SELECTION;
7574 END IF;
7575
7576 --This is an optional table with no selections - don't generate the COMBO, just generate
7577 --an EXCLUDE relation and exit the procedure.
7578
7579 vLogicLine := 'GS E ... ' || TO_CHAR(nReasonId) || NewLine ||
7580 'GL N ' || GENERATE_NAME(vBackIndex(1), vGridColumns(1)) || NewLine ||
7581 'GR L ' || GENERATE_NAME(vBackIndex(2), vGridColumns(2)) || NewLine;
7582 PACK;
7583 RETURN;
7584
7585 END IF;
7586
7587 ELSE
7588
7589 nDebug := 5000202;
7590
7591 v_tOptionId.DELETE;
7592 v_tPrimaryId.DELETE;
7593 v_OptionExists.DELETE;
7594
7595 --Read the list of participating options of defining or optional feature.
7596
7597 SELECT secondary_opt_id, primary_opt_id BULK COLLECT INTO v_tOptionId, v_tPrimaryId
7598 FROM cz_des_chart_cells
7599 WHERE rule_id = nRuleId
7600 AND secondary_feature_id = vGridColumns(i)
7601 AND secondary_feat_expl_id = v_tExplNodeId(vBackIndex(i))
7602 AND deleted_flag = FLAG_NOT_DELETED
7603 ORDER BY primary_opt_id;
7604
7605 FOR n IN 1..v_tOptionId.COUNT LOOP
7606
7607 IF(NOT glIndexByPsNodeId.EXISTS(v_tPrimaryId(n)))THEN
7608
7609 BEGIN
7610 SELECT name INTO errorMessage FROM cz_ps_nodes
7611 WHERE ps_node_id = v_tPrimaryId(n);
7612 EXCEPTION
7613 WHEN OTHERS THEN
7614 errorMessage := 'Unknown';
7615 END;
7616
7617 RAISE CZ_R_DELETED_OPTION;
7618 END IF;
7619
7620 --Bug #2257421. The list of corresponding primary options which participate in the rule should be
7621 --equal for all defining features.
7622 --v_tPrimaryOptId - the ordered list of primary options checked for the first defining feature.
7623 --v_tPrimaryId - the ordered list of primary options checked for the current feature.
7624
7625 IF((NOT v_tPrimaryOptId.EXISTS(n)) OR (v_tPrimaryOptId(n) > v_tPrimaryId(n)))THEN
7626
7627 --Too many selections made.
7628
7629 auxCount := glIndexByPsNodeId(vGridColumns(1));
7630 auxIndex := glIndexByPsNodeId(v_tPrimaryId(n));
7631 RAISE CZ_R_INCOMPLETE_DES_CHART;
7632
7633 ELSIF(v_tPrimaryOptId(n) < v_tPrimaryId(n))THEN
7634
7635 --Too few selections made.
7636
7637 auxCount := glIndexByPsNodeId(vGridColumns(1));
7638 auxIndex := glIndexByPsNodeId(v_tPrimaryOptId(n));
7639 RAISE CZ_R_INCOMPLETE_DES_CHART;
7640 END IF;
7641 END LOOP;
7642
7643 IF(v_tPrimaryOptId.EXISTS(v_tOptionId.COUNT + 1))THEN
7644
7645 --Too few selections made.
7646
7647 auxCount := glIndexByPsNodeId(vGridColumns(1));
7648 auxIndex := glIndexByPsNodeId(v_tPrimaryOptId(v_tOptionId.COUNT + 1));
7649 RAISE CZ_R_INCOMPLETE_DES_CHART;
7650 END IF;
7651 END IF;
7652
7653 startCount := itemCount;
7654
7655 FOR n IN 1..v_tOptionId.COUNT LOOP
7656
7657 --Make sure the option exists.
7658
7659 IF(NOT glIndexByPsNodeId.EXISTS(v_tOptionId(n)))THEN
7660
7661 BEGIN
7662 SELECT name INTO errorMessage FROM cz_ps_nodes
7663 WHERE ps_node_id = v_tOptionId(n);
7664 EXCEPTION
7665 WHEN OTHERS THEN
7666 errorMessage := 'Unknown';
7667 END;
7668
7669 RAISE CZ_R_DELETED_OPTION;
7670 END IF;
7671
7672 IF(NOT v_OptionExists.EXISTS(v_tOptionId(n)))THEN
7673
7674 nDebug := 5000203;
7675
7676 v_ItemLines(itemCount) := GENERATE_NAME(vBackIndex(i), v_tOptionId(n)) || ' ' || TO_CHAR(i - 1);
7677 v_OptionsUsed(itemCount) := v_tOptionId(n);
7678 v_OptionExists(v_tOptionId(n)) := itemCount;
7679 itemCount := itemCount + 1;
7680
7681 END IF;
7682
7683 nDebug := 5000204;
7684
7685 itemIndex := v_OptionExists(v_tOptionId(n));
7686 v_RowLinesIndex(n) := n;
7687
7688 IF(v_RowLines.EXISTS(n))THEN
7689 v_RowLines(n) := v_RowLines(n) || ' ' || TO_CHAR(itemIndex - 1);
7690 ELSE
7691 v_RowLines(n) := ' ' || TO_CHAR(itemIndex - 1);
7692 END IF;
7693
7694 END LOOP;
7695
7696 v_ExcludesRequired(i) := 0;
7697
7698 nDebug := 5000205;
7699
7700 IF(featOptionsCount(vGridColumns(i)) <> itemCount - startCount)THEN
7701
7702 v_StartOptionsUsed(i) := startCount;
7703 v_EndOptionsUsed(i) := itemCount - 1;
7704 v_ExcludesRequired(i) := 1;
7705
7706 END IF;
7707 END LOOP; --Validation and initial data for features
7708
7709 --Design chart rule specific validation - uniqueness of every column in the chart table.
7710 --At the current step this requirement is equivalent to the requirement of no duplicate
7711 --elements in v_RowLines table. We use the modified QuickSort algorythm to sort out the
7712 --table and then check for duplicate values in one pass.
7713
7714 IF(inSuffix = 0)THEN --This is the defining table
7715
7716 --We need a substring of the row starting with the 4th character
7717
7718 FOR i IN 1..v_RowLines.COUNT LOOP
7719 v_tailRowLines(i) := SUBSTR(v_RowLines(i),4);
7720 END LOOP;
7721
7722 SORT_ARRAY_INDEX(1, v_tailRowLines.COUNT);
7723 FOR i IN 2..v_tailRowLines.COUNT LOOP
7724 IF(v_tailRowLines(v_RowLinesIndex(i)) = v_tailRowLines(v_RowLinesIndex(i - 1)))THEN
7725
7726 --Duplicate combination of defining options for a primary option
7727 RAISE CZ_R_DUPLICATE_COMBINATION;
7728
7729 END IF;
7730 END LOOP;
7731 END IF; --This is the defining table
7732
7733 nDebug := 5000206;
7734
7735 FOR i IN 1..vGridColumns.COUNT LOOP
7736
7737 nDebug := 5000207;
7738
7739 IF(v_ExcludesRequired(i) = 1)THEN
7740
7741 nChild := glIndexByPsNodeId(vGridColumns(i)) + 1;
7742
7743 vLogicLine := 'GS E ... ' || TO_CHAR(nReasonId) || NewLine || 'GL N ';
7744 PACK;
7745
7746 nDebug := 5000208;
7747
7748 WHILE(glParentId.EXISTS(nChild) AND glParentId(nChild) = vGridColumns(i))LOOP
7749 IF(OPTION_EXISTS(i) = 0)THEN
7750 vLogicLine := GENERATE_NAME(vBackIndex(i), glPsNodeId(nChild)) || ' ';
7751 PACK;
7752 END IF;
7753 nChild := nChild + 1;
7754 END LOOP;
7755
7756 vLogicLine := NewLine || 'GR L ';
7757 PACK;
7758
7759 nDebug := 5000209;
7760
7761 FOR n IN 1..vGridColumns.COUNT LOOP
7762 IF(n <> i)THEN
7763 vLogicLine := GENERATE_NAME(vBackIndex(n), vGridColumns(n)) || ' ';
7764 PACK;
7765 END IF;
7766 END LOOP;
7767
7768 vLogicLine := NewLine;
7769 PACK;
7770 END IF; --Excludes required
7771 END LOOP;
7772
7773 nDebug := 5000210;
7774
7775 vLogicLine := 'OBJECT P_R' || TO_CHAR(nRuleId) || '_' || TO_CHAR(inSuffix) || NewLine ||
7776 'COMBO P_R' || TO_CHAR(nRuleId) || '_' || TO_CHAR(inSuffix) || ' ' || TO_CHAR(v_ItemLines.COUNT) || ' ' ||
7777 TO_CHAR(v_RowLines.COUNT) || ' ' || TO_CHAR(vGridColumns.COUNT) || ' ... ' ||
7778 TO_CHAR(nReasonId) || NewLine;
7779 PACK;
7780
7781 nDebug := 5000211;
7782
7783 FOR i IN 1..v_ItemLines.COUNT LOOP
7784
7785 vLogicLine := 'CI ' || TO_CHAR(i - 1) || ' ' || v_ItemLines(i) || NewLine;
7786 PACK;
7787
7788 END LOOP;
7789
7790 nDebug := 5000212;
7791
7792 FOR i IN 1..vGridColumns.COUNT LOOP
7793
7794 IF(GenerateGatedCombo = 0)THEN
7795
7796 IF(inSuffix = 0 OR i = 1)THEN
7797
7798 --This is the defining table or the primary feature in an optional table.
7799 --In this case we currently use actual feature's maximum value for the column
7800 --(or maximum_selected for BOM).
7801
7802 --Use intermediate variable instead of using NVL because this is faster
7803
7804 localNumber := glIndexByPsNodeId(vGridColumns(i));
7805 localString := TO_CHAR(glMaximum(localNumber));
7806
7807 --If it's a BOM item, we use maximum_selected instead of maximum
7808
7809 IF(glPsNodeType(localNumber) IN (PS_NODE_TYPE_BOM_MODEL,PS_NODE_TYPE_BOM_OPTIONCLASS,PS_NODE_TYPE_BOM_STANDARD))THEN
7810 localString := TO_CHAR(glMaximumSel(localNumber));
7811 END IF;
7812
7813 IF(localString IS NULL)THEN localString := '-1'; END IF;
7814
7815 ELSE
7816 --For optional features in optional tables we always use '-1' for columns' maximum value.
7817
7818 localString := '-1';
7819 END IF;
7820
7821 vLogicLine := ' O';
7822 ELSE
7823
7824 --Generate gated combinations: maximum is always -1, the 'G' argument is followed
7825 --by the feature name.
7826
7827 localString := '-1';
7828 vLogicLine := ' G ' || GENERATE_NAME(vBackIndex(i), vGridColumns(i));
7829 END IF;
7830
7831 vLogicLine := 'CC ' || TO_CHAR(i - 1) || ' 0 ' || localString || vLogicLine || NewLine;
7832 PACK;
7833
7834 END LOOP;
7835
7836 nDebug := 5000213;
7837
7838 FOR i IN 1..v_RowLines.COUNT LOOP
7839
7840 vLogicLine := 'CR ' || TO_CHAR(i - 1) || v_RowLines(i) || NewLine;
7841 PACK;
7842
7843 END LOOP;
7844
7845 nDebug := 5000214;
7846
7847 vLogicLine := 'COMBO_END' || NewLine;
7848 PACK;
7849 END;
7850 ---------------------------------------------------------------------------------------
7851 BEGIN
7852
7853 --Generate the defining table
7854
7855 nIndex := 2;
7856
7857 FOR i IN expressionStart..expressionEnd LOOP
7858
7859 IF(v_tFeatureType(i) = FEATURE_TYPE_DEFINING)THEN
7860 vGridColumns(nIndex) := v_tExprPsNodeId(i);
7861 vBackIndex(nIndex) := i;
7862 nIndex := nIndex + 1;
7863 ELSIF(v_tFeatureType(i) = FEATURE_TYPE_PRIMARY)THEN
7864 vGridColumns(1) := v_tExprPsNodeId(i);
7865 vBackIndex(1) := i;
7866 END IF;
7867
7868 END LOOP;
7869
7870 IF(vGridColumns.COUNT = 0)THEN
7871 RAISE CZ_R_NO_PRIMARY_FEATURE;
7872 ELSIF(vGridColumns.COUNT > 1)THEN
7873 GENERATE_COMPAT_TEMPLATE(0);
7874 vGridColumns.DELETE(2, vGridColumns.COUNT);
7875 vBackIndex.DELETE(2, vBackIndex.COUNT);
7876 END IF;
7877
7878 --Generate all the optional tables
7879
7880 nIndex := 1;
7881
7882 FOR i IN expressionStart..expressionEnd LOOP
7883
7884 IF(v_tFeatureType(i) = FEATURE_TYPE_OPTIONAL)THEN
7885 vGridColumns(2) := v_tExprPsNodeId(i);
7886 vBackIndex(2) := i;
7887 GENERATE_COMPAT_TEMPLATE(nIndex);
7888 nIndex := nIndex + 1;
7889 END IF;
7890
7891 END LOOP;
7892 END;
7893 ---------------------------------------------------------------------------------------
7894 BEGIN --GENERATE_RULES
7895
7896 nDebug := 0;
7897
7898 IF(t_RuleId.COUNT = 0)THEN
7899
7900 --This should be done only once during the generation session. The data is static and common
7901 --to all models.
7902
7903 SELECT rule_id, signature_id, name BULK COLLECT INTO t_RuleId, t_SignatureId, t_RuleName
7904 FROM cz_rules
7905 WHERE devl_project_id = 0
7906 AND seeded_flag = FLAG_SEEDED
7907 AND deleted_flag = FLAG_NOT_DELETED
7908 AND disabled_flag = FLAG_NOT_DISABLED;
7909
7910 --Make the table of names hashed by rule_id.
7911
7912 FOR i IN 1..t_RuleId.COUNT LOOP
7913
7914 h_SeededName(t_RuleId(i)) := UPPER(t_RuleName(i));
7915 h_ReportName(t_RuleId(i)) := t_RuleName(i);
7916 h_SignatureId(t_RuleId(i)) := t_SignatureId(i);
7917 END LOOP;
7918 END IF;
7919
7920 nDebug := 1;
7921
7922 --Make a quick and simple verification of all functional companions defined in this
7923 --project. All other rule related instances that do not reside in cz_rules can also
7924 --be processed in this section.
7925 --Added as a fix for the bug #2200481.
7926
7927 --Restoring this block in 11.5.10+, bug #3989382.
7928
7929 FOR c_func IN (SELECT component_id, model_ref_expl_id, program_string, name, rule_folder_id
7930 FROM cz_func_comp_specs
7931 WHERE devl_project_id = inComponentId
7932 AND deleted_flag = FLAG_NOT_DELETED) LOOP
7933
7934 IF(c_func.component_id IS NULL)THEN
7935
7936 --'Incomplete data: No base component specified for functional companion ''%COMPANION'' in model ''%MODELNAME''.'
7937 REPORT(CZ_UTILS.GET_TEXT('CZ_LCE_FC_BASE_COMPONENT', 'COMPANION', COMPANION_NAME(c_func.name, c_func.rule_folder_id), 'MODELNAME', glName(glIndexByPsNodeId(inComponentId))), 1);
7938
7939 ELSIF(c_func.program_string IS NULL)THEN
7940
7941 --'Incomplete data: No program string specified for functional companion ''%COMPANION'' in model ''%MODELNAME''.'
7942 REPORT(CZ_UTILS.GET_TEXT('CZ_LCE_FC_PROGRAM_STRING', 'COMPANION', COMPANION_NAME(c_func.name, c_func.rule_folder_id), 'MODELNAME', glName(glIndexByPsNodeId(inComponentId))), 1);
7943
7944 ELSIF(NOT glIndexByPsNodeId.EXISTS(c_func.component_id))THEN
7945
7946 --'Internal data error. Incorrect product structure data for functional companion ''%COMPANION'' in model ''%MODELNAME''.'
7947 REPORT(CZ_UTILS.GET_TEXT('CZ_LCE_INCORRECT_COMPONENT', 'COMPANION', COMPANION_NAME(c_func.name, c_func.rule_folder_id), 'MODELNAME', glName(glIndexByPsNodeId(inComponentId))), 1);
7948
7949 ELSIF(c_func.model_ref_expl_id IS NULL OR (NOT v_IndexByNodeId.EXISTS(c_func.model_ref_expl_id)))THEN
7950
7951 --'Internal data error. Incorrect explosion data for functional companion ''%COMPANION'' in model ''%MODELNAME''.'
7952 REPORT(CZ_UTILS.GET_TEXT('CZ_LCE_INCORRECT_EXPLOSION', 'COMPANION', COMPANION_NAME(c_func.name, c_func.rule_folder_id), 'MODELNAME', glName(glIndexByPsNodeId(inComponentId))), 1);
7953 END IF;
7954 END LOOP;
7955
7956 --Calculate downpathes for all explosion nodes here
7957
7958 nDebug := 1000007;
7959
7960 FOR i IN 1..v_NodeId.COUNT LOOP
7961
7962 nDebug := 1000002;
7963
7964 --Unconditionally create rule files for all the non-virtual components of the
7965 --model primary structure and all first-level reference nodes and put the INC
7966 --relation there.
7967
7968 IF(v_tVirtualFlag(i) = FLAG_NON_VIRTUAL AND v_tNodeDepth(i) > 0 AND
7969 (v_tChildModelExpl(i) IS NULL OR
7970 (v_tNodeType(i) = PS_NODE_TYPE_REFERENCE AND
7971 v_tChildModelExpl(v_IndexByNodeId(v_tParentId(i))) IS NULL)
7972 ))THEN
7973
7974 nDebug := 1000003;
7975
7976 nHeaderId := next_lce_header_id;
7977
7978 BEGIN
7979
7980 nDebug := 1000004;
7981
7982 --Insert the rule net logic header record into the table.
7983
7984 INSERT INTO cz_lce_headers
7985 (lce_header_id, gen_version, gen_header, component_id, net_type,
7986 devl_project_id, model_ref_expl_id, nbr_required_expls, deleted_flag)
7987 VALUES
7988 (nHeaderId, VersionString, GenHeader, v_tPsNodeId(i), LOGIC_NET_TYPE_MANDATORY,
7989 thisProjectId, v_NodeId(i), 1, FLAG_PENDING);
7990
7991 INSERT INTO cz_lce_load_specs
7992 (attachment_expl_id, lce_header_id, required_expl_id, attachment_comp_id,
7993 model_id, net_type, deleted_flag)
7994 VALUES
7995 (v_NodeId(i), nHeaderId, v_NodeId(i), v_tPsNodeId(i), thisProjectId,
7996 LOGIC_NET_TYPE_MANDATORY, FLAG_PENDING);
7997
7998 EXCEPTION
7999 WHEN OTHERS THEN
8000 errorMessage := SQLERRM;
8001 RAISE CZ_R_UNABLE_TO_CREATE_HEADER;
8002 END;
8003
8004 nDebug := 1000005;
8005
8006 NewHeaders(counterNewHeaders) := nHeaderId;
8007 NewHeadersComponents(counterNewHeaders) := v_tPsNodeId(i);
8008 NewHeadersExplosions(counterNewHeaders) := v_NodeId(i);
8009 counterNewHeaders := counterNewHeaders + 1;
8010
8011 nDebug := 1000006;
8012
8013 --Use intermediate variable instead of using NVL because this is faster
8014
8015 IF(v_tReferringId(i) IS NOT NULL)THEN
8016 localString := TO_CHAR(glPersistentId(v_tReferringId(i)));
8017 ELSE
8018 localString := TO_CHAR(glPersistentId(v_tPsNodeId(i)));
8019 END IF;
8020
8021 vLogicLine := 'CONTROL NOSPEC' || NewLine || 'VERSION 3 3' || NewLine || NewLine ||
8022 'REM -- Rules file for component: ' || TO_CHAR(v_tPsNodeId(i)) ||
8023 ', explosion node: ' || TO_CHAR(v_NodeId(i)) || NewLine || NewLine ||
8024 'EFF , , ' || NewLine || NewLine ||
8025 'INC 1 ' || PATH_DELIMITER || 'parent' || PATH_DELIMITER || 'P_' ||
8026 localString || '_ACTUALCOUNT round' || NewLine;
8027
8028 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES (nHeaderId, 1, vLogicLine);
8029
8030 v_tIsHeaderGenerated(v_NodeId(i)) := nHeaderId;
8031 v_tSequenceNbr(nHeaderId) := 2;
8032 v_tLogicNetType(nHeaderId) := LOGIC_NET_TYPE_MANDATORY;
8033
8034 --This variable is not supposed to be used as an accumulator for logic text. Instead, it
8035 --is used as a buffer every time to store a piece of text to be accumulated in vLogicText
8036 --(see PACK procedure). Therefore, it should be safe to null it out here even if it's not
8037 --necessary.
8038
8039 vLogicLine := NULL;
8040 END IF;
8041
8042 nDebug := 1000008;
8043
8044 --Here we will construct model level downpaths, which do not depend on a particular rule,
8045 --but only on explosion id within the model's explosion tree. When a particular rule is
8046 --assigned, downpaths of its participants may be prepended with segments including all A
8047 --type nodes from assignee to assignable. This corrected downpaths are always used when
8048 --generating names of the rule's participants.
8049
8050 nAux := v_NodeId(i);
8051 auxIndex := v_tNodeDepth(i) + 1;
8052
8053 IF(NOT v_NodeDownPath.EXISTS(nAux))THEN
8054
8055 nDebug := 1000009;
8056
8057 v_NodeDownPath(nAux) := ''; --start building the downpath
8058 v_NodeIndexPath.DELETE; --reset the table
8059
8060 --These all are index values in v_NodeIndexPath.
8061
8062 ConnectorIndex := 0;
8063 InstantiableIndex := auxIndex;
8064 OptionalIndex := auxIndex;
8065 TrackableIndex := auxIndex;
8066 nCounter := 1;
8067 auxCount := 0;
8068
8069 --Go all the way up from the explosion id and find the deepest D node and the
8070 --shallowest connector, and also the deepest optional node.
8071 --We are interested in the shallowest reference to a trackable model as well.
8072 --It will be used only if the root model is marked as a network container. If
8073 --there is no such reference above the explosion node the root node is used.
8074
8075 WHILE(nAux IS NOT NULL) LOOP
8076
8077 localCount := v_IndexByNodeId(nAux);
8078
8079 --Detect infinite loops which may be caused by data corruption.
8080
8081 auxCount := auxCount + 1;
8082 IF(auxCount > LOOP_DETECTED_LOOPS_NUMBER)THEN
8083
8084 errorMessage := glName(glIndexByPsNodeId(inProjectId));
8085 RAISE CZ_G_INVALID_MODEL_EXPLOSION;
8086 END IF;
8087
8088 --The next IF statement has been added as a fix for the bug #2802049. In case of circular
8089 --connectors it is possible that the explosion table of the second level-referenced model
8090 --contains pointers to ps node structure of the parent model that hasn't been read yet.
8091 --As in this case we do not need to generate downpaths, we can just ignore such pointers.
8092
8093 IF(NOT glIndexByPsNodeId.EXISTS(NVL(v_tReferringId(localCount), v_tPsNodeId(localCount))))THEN
8094
8095 auxCount := -1;
8096 EXIT;
8097 END IF;
8098
8099 IF(v_TypeByExplId(nAux) = EXPL_NODE_TYPE_CONNECTOR)THEN
8100
8101 ConnectorIndex := nCounter;
8102 ELSIF(v_TypeByExplId(nAux) = EXPL_NODE_TYPE_OPTIONAL AND OptionalIndex = auxIndex)THEN
8103
8104 OptionalIndex := nCounter;
8105 ELSIF(v_TypeByExplId(nAux) = EXPL_NODE_TYPE_INSTANTIABLE)THEN
8106
8107 IF(InstantiableIndex = auxIndex)THEN InstantiableIndex := nCounter; END IF;
8108
8109 IF(v_tNodeType(localCount) = PS_NODE_TYPE_REFERENCE AND
8110 glIbTrackable(v_tPsNodeId(localCount)) = FLAG_IB_TRACKABLE)THEN
8111
8112 TrackableIndex := nCounter;
8113 END IF;
8114 END IF;
8115
8116 v_NodeIndexPath(nCounter) := localCount;
8117 nCounter := nCounter + 1;
8118
8119 nAux := v_tParentId(localCount);
8120 END LOOP;
8121
8122 IF(auxCount = -1)THEN
8123
8124 --This is the 'circular connectors' case, we don't need any downpath.
8125 NULL;
8126
8127 ELSIF(InstantiableIndex < ConnectorIndex)THEN
8128
8129 --There are D nodes under connectors on the path - this explosion cannot participate
8130 --in any rule because it would be impossible to assign such a rule. No downpath.
8131 --For reporting purposes store the cz_ps_nodes indexes of the instantiable component
8132 --and the connector, corresponding exception/message is CZ_R_UNASSIGNABLE_RULE.
8133
8134 v_ProhibitInRules(v_NodeId(i)) := glIndexByPsNodeId(v_tPsNodeId(v_NodeIndexPath(InstantiableIndex)));
8135 v_ProhibitConnector(v_NodeId(i)) := glIndexByPsNodeId(v_tReferringId(v_NodeIndexPath(ConnectorIndex)));
8136
8137 ELSIF(OptionalIndex < ConnectorIndex)THEN
8138
8139 --There are A nodes under connectors on the path - this explosion cannot participate
8140 --in any rule - bug #2217450. No downpath.
8141 --For reporting purposes store the cz_ps_nodes indexes of the optional component
8142 --and the connector, corresponding exception/message is CZ_R_OPTIONAL_INSIDE.
8143
8144 v_ProhibitOptional(v_NodeId(i)) := glIndexByPsNodeId(v_tPsNodeId(v_NodeIndexPath(OptionalIndex)));
8145 v_ProhibitConnector(v_NodeId(i)) := glIndexByPsNodeId(v_tReferringId(v_NodeIndexPath(ConnectorIndex)));
8146
8147 ELSE
8148
8149 nDebug := 1000010;
8150
8151 AssignableIndex := InstantiableIndex;
8152
8153 --Find the deepest A node between the deepest D node and the shallowest connector.
8154 --This node is the assignable for the explosion id (can be the D node itself).
8155
8156 FOR n IN ConnectorIndex + 1..InstantiableIndex LOOP
8157 IF(v_tExplNodeType(v_NodeIndexPath(n)) = EXPL_NODE_TYPE_OPTIONAL)THEN
8158
8159 AssignableIndex := n;
8160 EXIT;
8161 END IF;
8162 END LOOP;
8163
8164 v_NodeLogicLevel(v_NodeId(i)) := v_tNodeDepth(v_NodeIndexPath(AssignableIndex));
8165
8166 --Store the main index of the assignable of the explosion node.
8167
8168 v_NodeAssignable(v_NodeId(i)) := v_NodeIndexPath(AssignableIndex);
8169
8170 --Store the main index of the deepest instantiable component above the explosion
8171 --node (may be the node itself if it is instantiable, or the root node if there
8172 --is no instantiable components on the way up from the explosion node).
8173
8174 v_NodeInstantiable(v_NodeId(i)) := v_NodeIndexPath(InstantiableIndex);
8175
8176 --Store the main index of the shallowest reference to a trackable model.
8177
8178 v_NodeTrackable(v_NodeId(i)) := v_NodeIndexPath(TrackableIndex);
8179
8180 nDebug := 1000011;
8181
8182 --Finally, construct the downpath from the assignable to the explosion id.
8183
8184 FOR n IN 1..AssignableIndex - 1 LOOP
8185 IF(v_tExplNodeType(v_NodeIndexPath(n)) IN (EXPL_NODE_TYPE_OPTIONAL, EXPL_NODE_TYPE_MANDATORY))THEN
8186
8187 --This is a mandatory reference or optional component, add N_<persistent_node_id>
8188 --to the path.
8189
8190 v_NodeDownPath(v_NodeId(i)) := PATH_DELIMITER || 'N_' ||
8191 TO_CHAR(glPersistentId(NVL(v_tReferringId(v_NodeIndexPath(n)), v_tPsNodeId(v_NodeIndexPath(n))))) ||
8192 v_NodeDownPath(v_NodeId(i));
8193
8194 ELSIF(v_tExplNodeType(v_NodeIndexPath(n)) = EXPL_NODE_TYPE_CONNECTOR)THEN
8195
8196 --This is a connector, add C_<model_ref_expl_id> to the path.
8197
8198 v_NodeDownPath(v_NodeId(i)) := PATH_DELIMITER || 'C_' ||
8199 TO_CHAR(v_NodeId(v_NodeIndexPath(n))) || v_NodeDownPath(v_NodeId(i));
8200
8201 --We will stop here, we do not want anything above the deepest connector to be reflected
8202 --in the path. Set a flag for this explosion because we do not want to prepend downpaths
8203 --for these explosions after the rule is assigned either. Actually, not just a flag, but
8204 --store the connector itself (main index) which may be useful for reporting purposes.
8205
8206 v_IsConnectorNet(v_NodeId(i)) := v_NodeIndexPath(n);
8207 EXIT;
8208 END IF;
8209 END LOOP;
8210 END IF;
8211 END IF;
8212 END LOOP;
8213
8214 nDebug := 2;
8215
8216 OPEN c_rules;
8217 LOOP
8218 BEGIN
8219
8220 --To generate effectivity information for the first rule. Uses the fact that
8221 --effective mask can not be null.
8222
8223 vUsageMask := NULL;
8224
8225 FETCH c_rules INTO
8226 nRuleId, nRuleType, nAntecedentId, nConsequentId, vRuleName, nReasonId, nRuleOperator,
8227 nRuleFolderId, nComponentId, nModelRefExplId, dEffFrom, dEffUntil, vUsageMask,
8228 nRuleEffSetId, nUnsatisfiedId, nUnsatisfiedSource, nPresentationFlag, vClassName;
8229 EXIT WHEN c_rules%NOTFOUND;
8230
8231 --Do nothing for those rules.
8232
8233 --Fix for the bug6502787
8234 IF(nRuleEffSetId IS NOT NULL)THEN
8235 IF(gvIndexBySetId.EXISTS(nRuleEffSetId))THEN
8236
8237 nDebug := 111111;
8238 dEffFrom := gvEffFrom(gvIndexBySetId(nRuleEffSetId));
8239 dEffUntil := gvEffUntil(gvIndexBySetId(nRuleEffSetId));
8240 ELSE
8241 --This is a fatal error - data corruption
8242 RAISE CZ_R_WRONG_EFFECTIVITY_SET;
8243 END IF;
8244 END IF;
8245
8246 IF(nRuleType NOT IN (RULE_TYPE_FUNC_COMP, RULE_TYPE_RULE_FOLDER, RULE_TYPE_BINDING_RULE,
8247 RULE_TYPE_RULE_SYS_PROP, RULE_TYPE_JAVA_SYS_PROP,
8248 RULE_TYPE_CAPTION_RULE, RULE_TYPE_DISPLAY_CONDITION))THEN
8249
8250 v_tExplNodeId.DELETE;
8251 v_tExprType.DELETE;
8252 v_tExprSubtype.DELETE;
8253 v_tExprId.DELETE;
8254 v_tExprParentId.DELETE;
8255 v_tExprTemplateId.DELETE;
8256 v_tExpressId.DELETE;
8257 v_tExprPsNodeId.DELETE;
8258 v_tRealPsNodeId.DELETE;
8259 v_tExprDataValue.DELETE;
8260 v_tExprPropertyId.DELETE;
8261 v_tConsequentFlag.DELETE;
8262 v_tExprParamIndex.DELETE;
8263 v_tExprArgumentName.DELETE;
8264 v_tExprDataType.DELETE;
8265 v_tExprDataNumValue.DELETE;
8266 v_tExprArgSignature.DELETE;
8267 v_tExprParSignature.DELETE;
8268 v_tArgumentIndex.DELETE;
8269 v_tDataType.DELETE;
8270 v_tArgumentName.DELETE;
8271 v_InstByLevel.DELETE;
8272 v_Assignable.DELETE;
8273 v_Participant.DELETE;
8274 v_DistinctIndex.DELETE;
8275 v_ParticipantIndex.DELETE;
8276 v_RuleConnectorNet.DELETE;
8277 v_LevelCount.DELETE;
8278 v_LevelIndex.DELETE;
8279 v_LevelType.DELETE;
8280 v_MarkLoadCondition.DELETE;
8281 v_LoadConditionId.DELETE;
8282 v_ChildrenIndex.DELETE;
8283 v_NodeUpPath.DELETE;
8284 v_IndexByExprNodeId.DELETE;
8285 v_NumberOfChildren.DELETE;
8286 v_ExplByPsNodeId.DELETE;
8287 v_RelativeNodePath.DELETE;
8288 parameterScope.DELETE;
8289 parameterName.DELETE;
8290
8291 jAntecedentRoot := NULL;
8292 jConsequentRoot := NULL;
8293 sUnsatisfiedId := NULL;
8294 RuleTemplateType := RULE_TYPE_UNKNOWN;
8295 numericLHS := 0;
8296 generateCompare := 0;
8297 t_prefix := 'T' || TO_CHAR(nRuleId) || '_';
8298
8299 --We need to reset the assigned down paths for every rule. Bug #3431166.
8300
8301 FOR i IN 1..v_NodeId.COUNT LOOP
8302
8303 --Make a copy that will be used as a rule-specific downpath which may have to be prepended
8304 --after the rule is assigned. It is this copy that will be used for name generation.
8305
8306 v_AssignedDownPath(v_NodeId(i)) := v_NodeDownPath(v_NodeId(i));
8307 END LOOP;
8308
8309 --Bug #3180819.
8310
8311 IF(nPresentationFlag IS NULL)THEN nPresentationFlag := FLAG_FREEFORM_RULE; END IF;
8312
8313 nDebug := 3;
8314
8315 --Get the rule participants, differently for different types of rules
8316
8317 IF(nRuleType = RULE_TYPE_JAVA_METHOD)THEN
8318
8319 --This is a CX. Call the CX validation procedure and continue with rules.
8320
8321 localRunId := thisRunId;
8322 cz_developer_utils_pvt.verify_special_rule(nRuleId, vRuleName, localRunId);
8323 RAISE CZ_LCE_CONTINUE;
8324
8325 ELSIF(nRuleType IN (RULE_TYPE_TEMPLATE, RULE_TYPE_EXPRESSION))THEN
8326
8327 --Set the unsatisfied message id string.
8328
8329 IF(nUnsatisfiedSource <> UNSATISFIED_TYPE_NONE)THEN
8330
8331 sUnsatisfiedId := TO_CHAR(nUnsatisfiedId);
8332 IF(sUnsatisfiedId IS NOT NULL)THEN sUnsatisfiedId := sUnsatisfiedId || ' '; END IF;
8333 END IF;
8334
8335 SELECT model_ref_expl_id, expr_type, expr_node_id, expr_parent_id, template_id,
8336 express_id, expr_subtype, ps_node_id, data_value, property_id, consequent_flag,
8337 param_index, argument_name, data_type, data_num_value, param_signature_id,
8338 relative_node_path
8339 BULK COLLECT INTO v_tExplNodeId, v_tExprType, v_tExprId, v_tExprParentId, v_tExprTemplateId,
8340 v_tExpressId, v_tExprSubtype, v_tExprPsNodeId, v_tExprDataValue,
8341 v_tExprPropertyId, v_tConsequentFlag, v_tExprParamIndex, v_tExprArgumentName,
8342 v_tExprDataType, v_tExprDataNumValue, v_tExprParSignature,
8343 v_RelativeNodePath
8344 FROM cz_expression_nodes
8345 WHERE rule_id = nRuleId
8346 AND expr_type <> EXPR_NODE_TYPE_PUNCT
8347 AND deleted_flag = FLAG_NOT_DELETED
8348 ORDER BY expr_parent_id, seq_nbr;
8349
8350 --Determine the size of the expression for all eventual purposes.
8351
8352 expressionSize := v_tExprType.COUNT;
8353
8354 IF(expressionSize = 0)THEN
8355 RAISE CZ_R_NO_PARTICIPANTS;
8356 END IF;
8357
8358 expressionStart := 1;
8359 expressionEnd := expressionSize;
8360
8361 FOR i IN expressionStart..expressionEnd LOOP
8362
8363 IF(v_tExprDataNumValue(i) IS NOT NULL)THEN v_tExprDataValue(i) := TO_CHAR(v_tExprDataNumValue(i)); END IF;
8364
8365 --Bug #3800352. Resolve the codes by names and emulate regular node types.
8366
8367 IF(v_tExprType(i) IN (EXPR_PROPERTYBYNAME, EXPR_OPERATORBYNAME, EXPR_JAVAPROPERTYBYNAME))THEN
8368
8369 FOR n IN 1..t_RuleId.COUNT LOOP
8370
8371 IF(t_RuleName(n) = v_tExprArgumentName(i))THEN v_tExprTemplateId(i) := t_RuleId(n); EXIT; END IF;
8372 END LOOP;
8373
8374 IF(v_tExprType(i) = EXPR_PROPERTYBYNAME)THEN
8375
8376 v_tExprType(i) := EXPR_SYS_PROP;
8377 ELSIF(v_tExprType(i) = EXPR_OPERATORBYNAME)THEN
8378
8379 v_tExprType(i) := EXPR_OPERATOR;
8380 ELSIF(v_tExprType(i) = EXPR_JAVAPROPERTYBYNAME)THEN
8381
8382 v_tExprType(i) := EXPR_JAVA_PROPERTY;
8383 END IF;
8384 END IF;
8385
8386 --Populate the expression node subtype from template_id for all expression nodes for backward
8387 --compatibility.
8388
8389 v_tExprSubtype(i) := v_tExprTemplateId(i);
8390
8391 --Use the code lookup to fix irregularities in new codes. May become unnecessary when real
8392 --metadata lookup is implemented.
8393
8394 IF(CodeByCodeLookup.EXISTS(v_tExprTemplateId(i)))THEN
8395
8396 v_tExprSubtype(i) := CodeByCodeLookup(v_tExprTemplateId(i));
8397 v_tExprTemplateId(i) := v_tExprSubtype(i);
8398 END IF;
8399
8400 IF(v_tExprParentId(i) IS NOT NULL)THEN
8401
8402 IF(v_NumberOfChildren.EXISTS(v_tExprParentId(i)))THEN
8403 v_NumberOfChildren(v_tExprParentId(i)) := v_NumberOfChildren(v_tExprParentId(i)) + 1;
8404 ELSE
8405 v_NumberOfChildren(v_tExprParentId(i)) := 1;
8406 END IF;
8407
8408 IF(NOT v_ChildrenIndex.EXISTS(v_tExprParentId(i)))THEN
8409 v_ChildrenIndex(v_tExprParentId(i)) := i;
8410 END IF;
8411 END IF;
8412
8413 --If this rule is against max of some component, mark this component as having such a rule.
8414 --Later we will generate INC for this component's actual max.
8415
8416 IF(v_tExprType(i) = EXPR_SYS_PROP AND h_SeededName.EXISTS(v_tExprSubtype(i)) AND
8417 h_SeededName(v_tExprSubtype(i)) = RULE_SYS_PROP_MAXINSTANCE AND
8418 v_tConsequentFlag(i) = FLAG_IS_CONSEQUENT)THEN
8419
8420 v_MaxRuleExists(v_tExplNodeId(i)) := 1;
8421 END IF;
8422
8423 --Add the indexing option.
8424
8425 v_IndexByExprNodeId(v_tExprId(i)) := i;
8426 END LOOP;
8427
8428 ELSIF(nRuleType = RULE_TYPE_COMPAT_TABLE)THEN
8429
8430 --Read all the features
8431
8432 SELECT model_ref_expl_id, feature_id, EXPR_NODE_TYPE_NODE
8433 BULK COLLECT INTO v_tExplNodeId, v_tExprPsNodeId, v_tExprType
8434 FROM cz_des_chart_features
8435 WHERE rule_id = nRuleId
8436 AND deleted_flag = FLAG_NOT_DELETED;
8437
8438 nDebug := 32;
8439
8440 --Determine the size of the expression for all eventual purposes.
8441
8442 expressionSize := v_tExprType.COUNT;
8443
8444 IF(expressionSize < 2)THEN
8445 RAISE CZ_R_NO_PARTICIPANTS;
8446 END IF;
8447
8448 expressionStart := 1;
8449 expressionEnd := expressionSize;
8450
8451 ELSIF(nRuleType = RULE_TYPE_DESIGNCHART_RULE)THEN
8452
8453 --Read all the features
8454
8455 SELECT model_ref_expl_id, feature_id, feature_type, EXPR_NODE_TYPE_NODE
8456 BULK COLLECT INTO v_tExplNodeId, v_tExprPsNodeId, v_tFeatureType, v_tExprType
8457 FROM cz_des_chart_features
8458 WHERE rule_id = nRuleId
8459 AND deleted_flag = FLAG_NOT_DELETED;
8460
8461 nDebug := 34;
8462
8463 --Determine the size of the expression for all eventual purposes.
8464
8465 expressionSize := v_tExprType.COUNT;
8466
8467 IF(expressionSize < 2)THEN
8468 RAISE CZ_R_NO_PARTICIPANTS;
8469 END IF;
8470
8471 expressionStart := 1;
8472 expressionEnd := expressionSize;
8473
8474 ELSE
8475
8476 --Unknown rule type. Do nothing for those rules, just go to the next rule.
8477
8478 RAISE CZ_LCE_CONTINUE;
8479 END IF;
8480
8481 --General rule data validation section - all rule types----------------------------Start
8482
8483 FOR i IN expressionStart..expressionEnd LOOP
8484
8485 IF(v_tExprPsNodeId(i) IS NOT NULL)THEN
8486 IF(NOT glIndexByPsNodeId.EXISTS(v_tExprPsNodeId(i)))THEN
8487
8488 nDebug := 35;
8489
8490 --Every participating node must actually exist in the product structure.
8491
8492 RAISE CZ_R_WRONG_EXPRESSION_NODE;
8493
8494 ELSIF(glPsNodeType(glIndexByPsNodeId(v_tExprPsNodeId(i))) = PS_NODE_TYPE_FEATURE AND
8495 glFeatureType(glIndexByPsNodeId(v_tExprPsNodeId(i))) = PS_NODE_FEATURE_TYPE_STRING)THEN
8496
8497 --A text feature cannot participate in any kind of rules.
8498
8499 localString := glName(glIndexByPsNodeId(v_tExprPsNodeId(i)));
8500 RAISE CZ_R_INCORRECT_FEATURE_TYPE;
8501
8502 ELSIF(glPsNodeType(glIndexByPsNodeId(v_tExprPsNodeId(i))) = PS_NODE_TYPE_CONNECTOR)THEN
8503
8504 --A connector cannot participate in any kind of rules.
8505
8506 RAISE CZ_R_CONNECTOR_RULE;
8507 END IF;
8508
8509 IF(v_tExplNodeId(i) IS NULL)THEN
8510
8511 nDebug := 36;
8512
8513 --Every not null ps_node_id should have a not null assosiated model_ref_expl_id (data corruption).
8514
8515 RAISE CZ_G_INVALID_RULE_EXPLOSION;
8516
8517 ELSIF(NOT v_IndexByNodeId.EXISTS(v_tExplNodeId(i)))THEN
8518
8519 nDebug := 37;
8520
8521 --All the participants' model_ref_expl_id must be in the current model's explosion table (data corruption).
8522
8523 RAISE CZ_G_INVALID_RULE_EXPLOSION;
8524
8525 END IF;
8526 END IF;
8527
8528 nDebug := 38;
8529
8530 IF(v_tExprType(i) IN (EXPR_NODE_TYPE_NODE, EXPR_PSNODEBYNAME))THEN
8531 IF(v_tExprPsNodeId(i) IS NULL)THEN
8532
8533 nDebug := 381;
8534
8535 --Every node type node must have assosiated ps_node_id.
8536
8537 RAISE CZ_R_INCORRECT_NODE_ID;
8538 END IF;
8539 ELSIF(v_tExprType(i) = EXPR_NODE_TYPE_LITERAL)THEN
8540 IF(v_tExprDataValue(i) IS NULL)THEN
8541
8542 nDebug := 382;
8543
8544 --Every literal must have not null value.
8545
8546 RAISE CZ_R_LITERAL_NO_VALUE;
8547 END IF;
8548 ELSIF(v_tExprType(i) = EXPR_NODE_TYPE_FEATPROP)THEN
8549 IF(v_tExprPsNodeId(i) IS NULL)THEN
8550
8551 nDebug := 383;
8552
8553 --Every feature property node must have assosiated ps_node_id.
8554
8555 RAISE CZ_R_INCORRECT_NODE_ID;
8556 ELSIF(v_tExprPropertyId(i) IS NULL)THEN
8557
8558 nDebug := 384;
8559
8560 --Every feature property node must have assosiated property_id.
8561
8562 RAISE CZ_R_FEATURE_NO_PROPERTY;
8563 END IF;
8564 END IF;
8565
8566 --Bug #4760372.
8567
8568 IF(v_tExprType(i) = EXPR_PSNODEBYNAME)THEN
8569
8570 --This will resolve the path if possible, populate ps_node_id and model_ref_expl_id with
8571 --resolved values and change the type of the expression node.
8572
8573 RESOLVE_NODE(SPLIT_PATH(v_RelativeNodePath(i)), v_tExprPsNodeId(i), v_tExplNodeId(i), v_tExprPsNodeId(i), v_tExplNodeId(i));
8574 v_tExprType(i) := EXPR_NODE_TYPE_NODE;
8575 END IF;
8576 END LOOP;
8577 --General rule data validation section-----------------------------------------------End
8578
8579 nDebug := 41;
8580
8581 nCounter := 0;
8582 distinctCount := 0;
8583 participantCount := 0;
8584 MaxDepthValue := 0;
8585 MaxDepthIndex := thisRootExplIndex;
8586
8587 FOR i IN expressionStart..expressionEnd LOOP
8588 IF(v_tExprPsNodeId(i) IS NOT NULL)THEN
8589
8590 participantCount := participantCount + 1;
8591 auxIndex := glIndexByPsNodeId(v_tExprPsNodeId(i));
8592
8593 --Soft fix the explosion nodes whenever necessary:
8594
8595 --When a rule has a reference node as a participant,Developer would put the explosion id
8596 --of the reference node itself instead of the explosion id of its parent. This should be
8597 --fixed in some cases (see below).
8598 --If a participant is a component, then it's the component's MIN,MAX or COUNT and actual
8599 --participant should be it's parent. However,it can also be features of the component or
8600 --some other (new) operator. That's why we make sure that the parent of the component is
8601 --the operator DOT and, in addition, the component is non-virtual.
8602
8603 --Later remark:
8604 --A reference, as well as a component, should be fixed only when they are in combination
8605 --with system property. So, it's not enough to check that the parent operator is DOT, we
8606 --also have to make sure that the another operand is EXPR_SYS_PROP with MIN,MAX or COUNT
8607 --subtype.
8608
8609 IF(glPsNodeType(auxIndex) = PS_NODE_TYPE_REFERENCE OR
8610 (glPsNodeType(auxIndex) = PS_NODE_TYPE_COMPONENT AND glVirtualFlag(auxIndex) = FLAG_NON_VIRTUAL))THEN
8611
8612 IF((v_ChildrenIndex.EXISTS(v_tExprId(i)) AND v_tExprType(v_ChildrenIndex(v_tExprId(i))) = EXPR_SYS_PROP AND
8613 h_SeededName.EXISTS(v_tExprSubtype(v_ChildrenIndex(v_tExprId(i)))) AND
8614 h_SeededName(v_tExprSubtype(v_ChildrenIndex(v_tExprId(i)))) IN (RULE_SYS_PROP_MININSTANCE, RULE_SYS_PROP_MAXINSTANCE, RULE_SYS_PROP_INSTANCECOUNT))
8615 )THEN
8616
8617 --SYS_PROP_COUNT has been removed from the above condition as a part of the fix for the
8618 --bug #2317427 - we do not want to fix explosion if it is a reference to a BOM ATO. For
8619 --such a reference SYS_PROP_COUNT means #Quantity.
8620
8621 --If this is a reference to a trackable model in a network container model, then this
8622 --rule is against its #Min or #Max, not #Quantity, and so it should be prohibited.
8623 --This exception does not just ignore the rule, it stops the generation.
8624
8625 IF(rootProjectType = MODEL_TYPE_CONTAINER_MODEL AND glIbTrackable(v_tExprPsNodeId(i)) = FLAG_IB_TRACKABLE)THEN
8626
8627 nParam := auxIndex;
8628 RAISE CZ_R_AGAINST_TRACKABLE;
8629 END IF;
8630
8631 v_tExplNodeId(i) := v_tParentId(v_IndexByNodeId(v_tExplNodeId(i)));
8632
8633 ELSIF(glPsNodeType(auxIndex) = PS_NODE_TYPE_REFERENCE)THEN
8634
8635 --If we are here, than this is a reference to a BOM model, because it should be prohibited
8636 --for a reference to a component to participate with anything other than it's MIN or MAX.
8637 --We will fix the corresponding PS_NODE_ID value to be not the reference node's PS_NODE_ID
8638 --but the PS_NODE_ID of the referenced BOM model. This is necessary to generate the correct
8639 --object name.
8640 --In some cases we still need to use the real reference's ps_node_id.
8641
8642 v_tRealPsNodeId(i) := v_tExprPsNodeId(i);
8643 v_tExprPsNodeId(i) := glReferenceId(v_tExprPsNodeId(i));
8644 END IF;
8645 END IF;
8646
8647 nDebug := 42;
8648
8649 --Select a participant and get its explosion id.
8650
8651 nAux := v_tExplNodeId(i);
8652
8653 IF(NOT v_Participant.EXISTS(nAux))THEN
8654
8655 nDebug := 43;
8656
8657 IF(v_ProhibitInRules.EXISTS(nAux))THEN
8658
8659 --This explosion node has D nodes under connectors on the way up in the explosion table.
8660 --It will be impossible to assign this rule, so just stop here.
8661
8662 localString := glName(glIndexByPsNodeId(v_tExprPsNodeId(i)));
8663 auxIndex := v_ProhibitInRules(nAux);
8664 auxCount := v_ProhibitConnector(nAux);
8665 RAISE CZ_R_UNASSIGNABLE_RULE;
8666
8667 ELSIF(v_ProhibitOptional.EXISTS(nAux))THEN
8668
8669 --This explosion node has A nodes under connectors on the way up in the explosion table.
8670 --Stop here - bug #2217450.
8671
8672 localString := glName(glIndexByPsNodeId(v_tExprPsNodeId(i)));
8673 auxIndex := v_ProhibitOptional(nAux);
8674 auxCount := v_ProhibitConnector(nAux);
8675 RAISE CZ_R_OPTIONAL_INSIDE;
8676 END IF;
8677
8678 --Add to the list of indexes of distinct participants' explosions.
8679
8680 v_Participant(nAux) := 1;
8681 distinctCount := distinctCount + 1;
8682 v_ParticipantIndex(distinctCount) := v_IndexByNodeId(nAux);
8683
8684 --The node is not prohibited from participating in rules, so both assignable exists and
8685 --corresponding deepest instantiable node is defined.
8686
8687 auxIndex := v_NodeInstantiable(nAux);
8688 auxCount := v_NodeAssignable(nAux);
8689
8690 --We mark the potential assignables to reflect the fact that the associated participant
8691 --belongs to a connector net. We need a separate table because this information is rule
8692 --specific while v_IsConnectorNet stores the explosion-specific information. A node can
8693 --be assignable for a connector's net participant in one rule but not in another.
8694
8695 IF(v_IsConnectorNet.EXISTS(nAux))THEN
8696
8697 v_RuleConnectorNet(auxIndex) := 1;
8698 v_RuleConnectorNet(auxCount) := 1;
8699 END IF;
8700
8701 --Select and store all the distinct assignables for all the current rule's participants.
8702 --Main indexes are stored in v_DistinctIndex. Also find the deepest D node among all of
8703 --participants here. MaxDepthValue is initialized to the root (0), so that if there are
8704 --no D nodes, the root node will act as one.
8705
8706 nDebug := 44;
8707
8708 IF(NOT v_Assignable.EXISTS(auxIndex))THEN
8709
8710 v_Assignable(auxIndex) := 1;
8711 nCounter := nCounter + 1;
8712 v_DistinctIndex(nCounter) := auxIndex;
8713
8714 IF(v_tNodeDepth(auxIndex) > MaxDepthValue)THEN
8715
8716 MaxDepthValue := v_tNodeDepth(auxIndex);
8717 MaxDepthIndex := auxIndex;
8718 END IF;
8719 END IF;
8720
8721 IF(NOT v_Assignable.EXISTS(auxCount))THEN
8722
8723 v_Assignable(auxCount) := 1;
8724 nCounter := nCounter + 1;
8725 v_DistinctIndex(nCounter) := auxCount;
8726 END IF;
8727 END IF; --This is a distinct participant.
8728
8729 v_ExplByPsNodeId(v_tExprPsNodeId(i)) := v_tExplNodeId(i);
8730
8731 END IF; --This is a participant.
8732 END LOOP;
8733
8734 nDebug := 45;
8735
8736 --Now populate the <index in memory>(NODE_DEPTH) table for assignables of any type which
8737 --are above the deepest D component. They should form a chain, without duplicates on the
8738 --same level. Here we verify that there are no two components on the same level. This is
8739 --necessary but not sufficient for the rule to be valid.
8740
8741 FOR i IN 1..v_DistinctIndex.COUNT LOOP
8742
8743 auxIndex := v_DistinctIndex(i);
8744
8745 IF(v_tNodeDepth(auxIndex) <= MaxDepthValue)THEN
8746 IF(v_InstByLevel.EXISTS(v_tNodeDepth(auxIndex)))THEN
8747
8748 --There is already a node on this level. Two or more non-virtual components on the
8749 --same level are prohibited.
8750
8751 auxCount := glIndexByPsNodeId(v_tPsNodeId(auxIndex));
8752 auxIndex := glIndexByPsNodeId(v_tPsNodeId(v_InstByLevel(v_tNodeDepth(auxIndex))));
8753 RAISE CZ_R_CONFLICTING_NODES;
8754 ELSE
8755
8756 --This level is now occupied by a node with memory index auxIndex.
8757
8758 v_InstByLevel(v_tNodeDepth(auxIndex)) := auxIndex;
8759 END IF;
8760 END IF;
8761 END LOOP;
8762
8763 nDebug := 46;
8764
8765 --Now we make sure that if we move up from the deepest D assignable, we will step over
8766 --all other assignable which are above this D, so they all form a chain.
8767 --We start with the deepest D component and move up to its parent and so on thus going
8768 --through every level in the hierarchy. On every level, if an assignable exists there,
8769 --we make sure that this node is what we expect - the parent we just moved up to.
8770
8771 nCounter := 0;
8772 auxIndex := MaxDepthIndex;
8773
8774 LOOP
8775 IF(v_InstByLevel.EXISTS(v_tNodeDepth(auxIndex)))THEN
8776 IF(v_InstByLevel(v_tNodeDepth(auxIndex)) <> auxIndex)THEN
8777
8778 --Incorrect node on the level. The rule goes across non-virual boundaries.
8779
8780 auxCount := glIndexByPsNodeId(v_tPsNodeId(v_InstByLevel(v_tNodeDepth(auxIndex))));
8781 auxIndex := glIndexByPsNodeId(v_tPsNodeId(MaxDepthIndex));
8782 RAISE CZ_R_INCORRECT_NODE_LEVEL;
8783 END IF;
8784 nCounter := nCounter + 1;
8785 END IF;
8786
8787 EXIT WHEN nCounter = v_InstByLevel.COUNT OR v_tParentId(auxIndex) IS NULL;
8788 auxIndex := v_IndexByNodeId(v_tParentId(auxIndex));
8789 END LOOP;
8790
8791 nDebug := 47;
8792
8793 --We verified that on the way up from the deepest D node we pass ONLY through eligible
8794 --assignables. Now lets see if we passed through ALL of them.
8795
8796 IF(nCounter <> v_InstByLevel.COUNT)THEN
8797
8798 --Not all the assignables have been passed on the way up. The rule goes across
8799 --non-virual boundaries.
8800
8801 RAISE CZ_R_INVALID_RULE;
8802 END IF;
8803
8804 --So, there exists the deepest type D assignable (it can be the root node) and we verified
8805 --that above it there is no non-virtual boundaries crossing. However, if there are A type
8806 --assignables beneath that D node, we want to assign the rule to the least common ancestor.
8807 --Or there may be not assignables but just regular A nodes between assignables and D.
8808
8809 --First of all, let us see if there are connector's nets attached to the deepest component
8810 --among the rule participants, because if there are, then the rule will be assigned to the
8811 --deepst D already found and there's no need to work with A type components. Example:
8812
8813 -- M
8814 -- |_D
8815 -- |_A0
8816 -- | |_A
8817 -- | | |_F2
8818 -- | |_A
8819 -- | |_F3
8820 -- |
8821 -- |_Connector->M1-F4
8822
8823 --For both rules relating either (F2, F3) or (F2, F3, F4), D is the deepest D node. However,
8824 --the first rule should be assigned to A0 while the second rule should be assigned to D.
8825 --Reference bug #2188507.
8826
8827 --We also identify possible connector's nets attached to a node above the deepest D node.
8828 --Such explosions will have assignables above the deepest D and so may have passed all the
8829 --tests above, but a rule may still cross non-virual boundaries. Example:
8830
8831 -- M
8832 -- |_D
8833 -- | |_A
8834 -- | |_F2
8835 -- |
8836 -- |___Connector->M1-F4
8837
8838 --F4 has M as its assignable, and although M and D form a good chain, an (F2, F4) rule is
8839 --prohibited.
8840 --Reference bug #2190399.
8841
8842 --This block can be optimized to use v_RuleConnectorNet table which was introduced later.
8843
8844 auxCount := 0;
8845
8846 FOR i IN 1..v_ParticipantIndex.COUNT LOOP
8847
8848 nAux := v_NodeId(v_ParticipantIndex(i));
8849
8850 IF(v_IsConnectorNet.EXISTS(nAux))THEN
8851 IF(v_tNodeDepth(v_NodeAssignable(nAux)) < MaxDepthValue)THEN
8852
8853 --This is a connector's net attached to a node above the deepest D assignable, report
8854 --the rule.
8855
8856 auxCount := glIndexByPsNodeId(v_tReferringId(v_IsConnectorNet(nAux)));
8857 auxIndex := glIndexByPsNodeId(v_tPsNodeId(MaxDepthIndex));
8858 RAISE CZ_R_CONNECTOR_ASIDE;
8859 ELSIF(v_NodeAssignable(nAux) = MaxDepthIndex)THEN
8860
8861 --This is a connector's net attached to the D, so the rule will be assigned to the D.
8862
8863 auxCount := 1;
8864
8865 --Just one attached net is enough, but we cannot exit here because we need to examine
8866 --all other participants on account of connector's nets attached above the D node
8867 --(the previous IF does that).
8868 END IF;
8869 END IF;
8870 END LOOP;
8871
8872 IF(auxCount = 0)THEN
8873
8874 --We know that the rule can be assigned somewhere under the deepest D node. It can be
8875 --one of the A type nodes under the deepest D, assignable or not. We start from every
8876 --assignable A node underneath the deepest D and go up all the way to the D. If we do
8877 --not end up on the deepest D, the rule crosses non-virtual boundaries and is invalid.
8878
8879 --On the way up we collect the following information:
8880
8881 -- for every level the number of distinct components of any type on this level
8882 -- (v_LevelCount);
8883 -- index of the first of such components (v_LevelIndex);
8884 -- type of the first of such components (v_LevelType);
8885
8886 nDebug := 48;
8887
8888 nCounter := MaxDepthValue;
8889
8890 FOR i IN 1..v_DistinctIndex.COUNT LOOP
8891
8892 auxIndex := v_DistinctIndex(i);
8893 nAux := v_tNodeDepth(auxIndex);
8894
8895 IF(v_tExplNodeType(auxIndex) = EXPL_NODE_TYPE_OPTIONAL AND nAux > MaxDepthValue)THEN
8896
8897 IF(nCounter < nAux)THEN nCounter := nAux; END IF;
8898
8899 FOR n IN REVERSE MaxDepthValue + 1..nAux LOOP
8900
8901 IF(NOT v_LevelCount.EXISTS(nAux))THEN
8902
8903 v_LevelCount(nAux) := 1;
8904 v_LevelIndex(nAux) := auxIndex;
8905 v_LevelType(nAux) := v_tExplNodeType(auxIndex);
8906 END IF;
8907
8908 IF(auxIndex <> v_LevelIndex(nAux))THEN
8909
8910 v_LevelCount(nAux) := v_LevelCount(nAux) + 1;
8911 END IF;
8912
8913 auxIndex := v_IndexByNodeId(v_tParentId(auxIndex));
8914 nAux := nAux - 1;
8915 END LOOP;
8916
8917 IF(auxIndex <> MaxDepthIndex)THEN
8918
8919 --The way up from the A node doesn't pass through the D node on level MaxDepthValue.
8920 --Crossing of non-virtual boundaries detected.
8921
8922 auxCount := glIndexByPsNodeId(v_tPsNodeId(v_DistinctIndex(i)));
8923 auxIndex := glIndexByPsNodeId(v_tPsNodeId(MaxDepthIndex));
8924 RAISE CZ_R_OPTIONAL_ASIDE;
8925 END IF;
8926 END IF;
8927 END LOOP;
8928
8929 nDebug := 49;
8930
8931 --We want to find the deepest A component we can assign the rule to. So we move from the
8932 --top down shifting MaxDepthIndex with every A component we find. When we hit a fork, we
8933 --stop.
8934
8935 FOR i IN MaxDepthValue + 1..nCounter LOOP
8936
8937 IF(v_LevelCount(i) = 1 AND v_LevelType(i) = EXPL_NODE_TYPE_OPTIONAL)THEN
8938
8939 MaxDepthIndex := v_LevelIndex(i);
8940 END IF;
8941
8942 --We stop when we hit a fork or when we see that there is a connector net attached to
8943 --the optional component which is another kind of fork. Example:
8944
8945 -- A1
8946 -- |_A2
8947 -- |_A3
8948 -- | |_A4
8949 -- |
8950 -- |_Connector->participant
8951
8952 --We don't want to go below A2.
8953
8954 IF(v_LevelCount(i) > 1 OR v_RuleConnectorNet.EXISTS(v_LevelIndex(i))) THEN
8955
8956 EXIT;
8957 END IF;
8958 END LOOP;
8959 END IF; --We finished processing the tree of A nodes beneath the deepest D node which
8960 --may have resulted in assigning the rule to an A node under the deepest D.
8961
8962 --If this rule is defined in a network container model, it can't have participants across
8963 --instantiable references to trackable models. We have already calculated indexes of such
8964 --references for every explosion. The requirement above means that, if one of the indexes
8965 --belongs to a non-trackable model, then all the indexes should belong to a non-trackable
8966 --model.
8967
8968 IF(rootProjectType = MODEL_TYPE_CONTAINER_MODEL)THEN
8969
8970 localCount := 0;
8971
8972 FOR i IN 1..v_ParticipantIndex.COUNT LOOP
8973
8974 IF(glIbTrackable(v_tPsNodeId(v_NodeTrackable(v_NodeId(v_ParticipantIndex(i))))) = FLAG_NOT_IB_TRACKABLE)
8975 THEN localCount := localCount + 1; END IF;
8976 END LOOP;
8977
8978 IF(localCount > 0 AND localCount < v_ParticipantIndex.COUNT)THEN
8979
8980 RAISE CZ_R_ACROSS_TRACKABLE;
8981 END IF;
8982 END IF;
8983
8984 nDebug := 490;
8985
8986 --The rule is assigned to this component (identified by model_ref_expl_id). This variable
8987 --is used mostly for identification of rule logic files, but also in rule generation code.
8988
8989 MaxDepthId := v_NodeId(MaxDepthIndex);
8990 MaxDepthValue := v_tNodeDepth(MaxDepthIndex);
8991
8992 nDebug := 50;
8993
8994 --We need to prepend downpaths for all the distinct participating explosions. If the
8995 --assignable of an explosion id is deeper than the rule's assignee, we are going to
8996 --prepend the downpath with all optional (type A) components or mandatory references
8997 --on the way down from the assignee to the assignable. We do not need to change the
8998 --node's logic level.
8999 --We do not prepend downpaths for explosions corresponding to connectors.
9000
9001 FOR i IN 1..v_ParticipantIndex.COUNT LOOP
9002
9003 nAux := v_NodeId(v_ParticipantIndex(i));
9004
9005 IF(NOT v_IsConnectorNet.EXISTS(nAux))THEN
9006
9007 auxIndex := v_NodeAssignable(nAux);
9008
9009 WHILE(v_tNodeDepth(auxIndex) > MaxDepthValue)LOOP
9010 IF(v_tExplNodeType(auxIndex) IN (EXPL_NODE_TYPE_OPTIONAL, EXPL_NODE_TYPE_MANDATORY))THEN
9011
9012 v_AssignedDownPath(nAux) := PATH_DELIMITER || 'N_' ||
9013 TO_CHAR(glPersistentId(NVL(v_tReferringId(auxIndex), v_tPsNodeId(auxIndex)))) ||
9014 v_AssignedDownPath(nAux);
9015 END IF;
9016
9017 auxIndex := v_IndexByNodeId(v_tParentId(auxIndex));
9018 END LOOP;
9019 END IF;
9020 END LOOP;
9021
9022 nDebug := 51;
9023
9024 --Now we can go ahead and collect the load conditions for this rule. Those would be all
9025 --type A (optional) and C (connector) descendants of the rule assignee. To collect them
9026 --we need to go up from each (distinct) rule participant's explosion id (index).
9027 --There may also be no load conditions at all and then this is the 'standard' rule file
9028 --identified by explosion id of the assignee as a load condition (NET_TYPE = 2).
9029
9030 FOR i IN 1..v_ParticipantIndex.COUNT LOOP
9031
9032 auxIndex := v_ParticipantIndex(i);
9033
9034 WHILE(v_tNodeDepth(auxIndex) > MaxDepthValue AND v_tParentId(auxIndex) IS NOT NULL) LOOP
9035
9036 IF(v_tExplNodeType(auxIndex) IN (EXPL_NODE_TYPE_OPTIONAL, EXPL_NODE_TYPE_CONNECTOR))THEN
9037
9038 --It is enough to just mark the index as a load condition.
9039
9040 v_MarkLoadCondition(auxIndex) := 1;
9041 END IF;
9042
9043 auxIndex := v_IndexByNodeId(v_tParentId(auxIndex));
9044 END LOOP;
9045 END LOOP;
9046
9047 nDebug := 52;
9048
9049 nHeaderId := NEVER_EXISTS_ID;
9050
9051 IF(v_MarkLoadCondition.COUNT = 0)THEN
9052
9053 --This is going to be a mandatory (standard) rule file.
9054
9055 logicNetType := LOGIC_NET_TYPE_MANDATORY;
9056 v_LoadConditionId(1) := MaxDepthId;
9057 IF(v_tIsHeaderGenerated.EXISTS(MaxDepthId))THEN
9058
9059 nHeaderId := v_tIsHeaderGenerated(MaxDepthId);
9060 END IF;
9061 ELSE
9062
9063 --There are load conditions, so this is going to be a network logic file.
9064
9065 logicNetType := LOGIC_NET_TYPE_NETWORK;
9066
9067 nDebug := 53;
9068
9069 --Generate the load condition string. Note that with the algorithm used condition nodes
9070 --are ordered, otherwise it would make no sense.
9071 --There is currently no check for not to exceed the length of the localString.
9072
9073 localString := NULL;
9074 nCounter := 0;
9075
9076 FOR i IN 1..v_NodeId.COUNT LOOP
9077 IF(v_MarkLoadCondition.EXISTS(i))THEN
9078
9079 nCounter := nCounter + 1;
9080 v_LoadConditionId(nCounter) := v_NodeId(i);
9081 localString := localString || ':' || TO_CHAR(v_NodeId(i));
9082 END IF;
9083 END LOOP;
9084
9085 nDebug := 54;
9086
9087 nCounter := 0;
9088
9089 FOR i IN 1..v_LoadConditions.COUNT LOOP
9090 IF(localString = v_LoadConditions(i))THEN
9091
9092 --Load condition found, fetch the corresponding header and exit the loop.
9093
9094 nHeaderId := v_LoadHeaders(i);
9095 nCounter := 1;
9096 EXIT;
9097 END IF;
9098 END LOOP;
9099
9100 IF(nCounter = 0)THEN
9101
9102 --A new load condition, add it to the table. Corresponding header will be
9103 --generated and added later.
9104
9105 v_LoadConditions(v_LoadConditions.COUNT + 1) := localString;
9106 END IF;
9107 END IF;
9108
9109 nCounter := v_LoadConditionId.COUNT;
9110
9111 nDebug := 7;
9112
9113 --Generate a new logic header if necessary.
9114
9115 IF(nHeaderId = NEVER_EXISTS_ID)THEN
9116
9117 nHeaderId := next_lce_header_id;
9118
9119 BEGIN
9120
9121 --Insert the rule net logic header record into the table.
9122
9123 INSERT INTO cz_lce_headers
9124 (lce_header_id, gen_version, gen_header, component_id, net_type,
9125 devl_project_id, model_ref_expl_id, nbr_required_expls, deleted_flag)
9126 VALUES
9127 (nHeaderId, VersionString, GenHeader, v_tPsNodeId(v_IndexByNodeId(MaxDepthId)),
9128 logicNetType, thisProjectId, MaxDepthId, nCounter, FLAG_PENDING);
9129
9130 FOR i IN 1..nCounter LOOP
9131
9132 nAux := v_LoadConditionId(i);
9133
9134 --The following statement populates the new ALIAS_NAME column introduced as a fix
9135 --for the bug #2214414. The column is populated with C_<model_ref_expl_id> for
9136 --connector conditions and with NULL for other conditions (optional components).
9137
9138 INSERT INTO cz_lce_load_specs
9139 (attachment_expl_id, lce_header_id, required_expl_id, attachment_comp_id,
9140 model_id, net_type, deleted_flag, alias_name)
9141 VALUES
9142 (MaxDepthId, nHeaderId, nAux, v_tPsNodeId(v_IndexByNodeId(MaxDepthId)),
9143 thisProjectId, logicNetType, FLAG_PENDING,
9144 DECODE(v_tExplNodeType(v_IndexByNodeId(nAux)), EXPL_NODE_TYPE_CONNECTOR, 'C_' || nAux, NULL));
9145 END LOOP;
9146
9147 EXCEPTION
9148 WHEN OTHERS THEN
9149 errorMessage := SQLERRM;
9150 RAISE CZ_R_UNABLE_TO_CREATE_HEADER;
9151 END;
9152
9153 NewHeaders(counterNewHeaders) := nHeaderId;
9154 NewHeadersComponents(counterNewHeaders) := v_tPsNodeId(v_IndexByNodeId(MaxDepthId));
9155 NewHeadersExplosions(counterNewHeaders) := MaxDepthId;
9156 counterNewHeaders := counterNewHeaders + 1;
9157
9158 IF(logicNetType = LOGIC_NET_TYPE_MANDATORY)THEN
9159
9160 v_tIsHeaderGenerated(MaxDepthId) := nHeaderId;
9161 ELSE
9162
9163 v_LoadHeaders(v_LoadHeaders.COUNT + 1) := nHeaderId;
9164 END IF;
9165
9166 v_tSequenceNbr(nHeaderId) := 1;
9167 v_tLogicNetType(nHeaderId) := logicNetType;
9168 nNewLogicFileFlag := 1;
9169 END IF;
9170
9171 nRuleAssignedLevel := v_tNodeDepth(v_IndexByNodeId(MaxDepthId));
9172
9173 --If the logic file has changed then we need to flush off the buffer
9174
9175 IF(nHeaderId <> nPreviousHeaderId)THEN
9176
9177 IF(vLogicText IS NOT NULL)THEN
9178 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
9179 (nPreviousHeaderId, v_tSequenceNbr(nPreviousHeaderId), vLogicText);
9180 vLogicText := NULL;
9181 v_tSequenceNbr(nPreviousHeaderId) := v_tSequenceNbr(nPreviousHeaderId) + 1;
9182 END IF;
9183
9184 END IF;
9185
9186 nPreviousHeaderId := nHeaderId;
9187
9188 IF(nNewLogicFileFlag = 1)THEN
9189
9190 --This is a new logic file, put the header lines in
9191
9192 vLogicLine := 'CONTROL NOSPEC' || NewLine || 'VERSION 3 3' || NewLine || NewLine ||
9193 'REM -- Rules file for component: ' || TO_CHAR(v_tPsNodeId(v_IndexByNodeId(MaxDepthId))) ||
9194 ', explosion node: ' || TO_CHAR(MaxDepthId) || NewLine || NewLine;
9195 PACK;
9196 nNewLogicFileFlag := 0;
9197
9198 END IF;
9199
9200 nDebug := 8;
9201
9202 --Prepare the effective date interval.
9203 --First get the effective date interval either from an effectivity set or
9204 --from the local values.
9205
9206 IF(nRuleEffSetId IS NOT NULL)THEN
9207 IF(gvIndexBySetId.EXISTS(nRuleEffSetId))THEN
9208
9209 nDebug := 8000100;
9210
9211 CurrentEffFrom := gvEffFrom(gvIndexBySetId(nRuleEffSetId));
9212 CurrentEffUntil := gvEffUntil(gvIndexBySetId(nRuleEffSetId));
9213
9214 --Fix for the bug6502787
9215 dEffFrom := CurrentEffFrom;
9216 dEffUntil:= CurrentEffUntil;
9217 ELSE
9218 --This is a fatal error - data corruption
9219 RAISE CZ_R_WRONG_EFFECTIVITY_SET;
9220 END IF;
9221 ELSE
9222 CurrentEffFrom := dEffFrom;
9223 CurrentEffUntil := dEffUntil;
9224 END IF;
9225
9226 nDebug := 8000101;
9227
9228 --Make sure effective dates are not null. Usage mask is not null anyway.
9229
9230 IF(CurrentEffFrom IS NULL)THEN CurrentEffFrom := EpochBeginDate; END IF;
9231 IF(CurrentEffUntil IS NULL)THEN CurrentEffUntil := EpochEndDate; END IF;
9232
9233 dEffFrom := CurrentEffFrom;
9234 dEffUntil := CurrentEffUntil;
9235
9236 IF((NOT PrevRuleEffFrom.EXISTS(nHeaderId)) OR
9237 (CurrentEffFrom <> PrevRuleEffFrom(nHeaderId)) OR (CurrentEffUntil <> PrevRuleEffUntil(nHeaderId)) OR
9238 (vUsageMask <> PrevRuleUsageMask(nHeaderId)))THEN
9239
9240 vLogicLine := LTRIM(vUsageMask, '0');
9241 IF(vLogicLine IS NOT NULL) THEN
9242 vLogicLine := EffUsagePrefix || vLogicLine;
9243 END IF;
9244
9245 IF(CurrentEffFrom = EpochBeginDate)THEN
9246 CurrentFromDate := NULL;
9247 ELSE
9248 CurrentFromDate := TO_CHAR(CurrentEffFrom, EffDateFormat);
9249 END IF;
9250
9251 IF(CurrentEffUntil = EpochEndDate)THEN
9252 CurrentUntilDate := NULL;
9253 ELSE
9254 CurrentUntilDate := TO_CHAR(CurrentEffUntil, EffDateFormat);
9255 END IF;
9256
9257 vLogicLine := 'EFF ' || CurrentFromDate || ', ' || CurrentUntilDate || ', ' || vLogicLine || NewLine;
9258 PACK;
9259
9260 PrevRuleEffFrom(nHeaderId) := CurrentEffFrom;
9261 PrevRuleEffUntil(nHeaderId) := CurrentEffUntil;
9262 PrevRuleUsageMask(nHeaderId) := vUsageMask;
9263 END IF;
9264
9265 nDebug := 8000102;
9266
9267 --Expression generation
9268
9269 IF(nRuleType IN (RULE_TYPE_TEMPLATE, RULE_TYPE_EXPRESSION))THEN
9270
9271 FOR i IN expressionStart..expressionEnd LOOP
9272 IF(v_tExprParentId(i) IS NULL)THEN
9273
9274 --Because of the ordering by expr_parent_id, all the expression tree roots will be at the end
9275 --after all their children. As soon as we hit the first of them we can start generating.
9276 --The construction of children lookup arrays has been moved directly after reading the
9277 --expression tree.
9278
9279 --Bugs #5160714, #5184017. Reset optimization and other parameters per rule. It is not enough
9280 --to do it once after for each rule record because rule text may consist of several rules.
9281 --These parameter are not used for other rule types.
9282
9283 optimizeChain := OPTIMIZATION_UNKNOWN;
9284 optimizeContribute := OPTIMIZATION_UNKNOWN;
9285 jAntecedentRoot := NULL;
9286 jConsequentRoot := NULL;
9287 RuleTemplateType := RULE_TYPE_UNKNOWN;
9288 numericLHS := 0;
9289 generateCompare := 0;
9290
9291 returnStringArray := GENERATE_EXPRESSION(i, returnListType);
9292 END IF;
9293 END LOOP;
9294 ELSIF(nRuleType = RULE_TYPE_COMPAT_TABLE)THEN
9295
9296 GENERATE_COMPATIBILITY_TABLE;
9297 ELSIF(nRuleType = RULE_TYPE_DESIGNCHART_RULE)THEN
9298
9299 GENERATE_DESIGNCHART_RULE;
9300 END IF; --End expression and rule generation
9301 END IF; --Not a rule folder or functional companion
9302
9303 --This block handles the exceptions during a rule generation. Every such exception
9304 --will stop generation only for the particular rule if not re-raised here.
9305
9306 EXCEPTION
9307 WHEN CZ_R_UNKNOWN_RULE_TYPE THEN
9308 --'Unknown rule type, rule ''%RULENAME'' ignored'
9309 REPORT(CZ_UTILS.GET_TEXT('CZ_R_UNKNOWN_RULE_TYPE', 'RULENAME', RULE_NAME), 1);
9310 PACK;
9311 WHEN CZ_R_INVALID_RULE THEN
9312 --'Rule ''%RULENAME'' cannot be generated because it relates an incorrect combination of components. Rule ignored.'
9313 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INVALID_RULE', 'RULENAME', RULE_NAME), 1);
9314 PACK;
9315 WHEN CZ_R_UNASSIGNABLE_RULE THEN
9316 --'Rule ''%RULENAME'' cannot be generated because the node ''%NODENAME'' is a descendant of the multiply
9317 -- instantiable component ''%COMPONENT'' inside the connected model ''%CONNECTOR'', and therefore cannot
9318 -- participate in rules. Rule ignored.'
9319 REPORT(CZ_UTILS.GET_TEXT('CZ_R_UNASSIGNABLE_RULE', 'NODENAME', localString, 'COMPONENT', glName(auxIndex), 'CONNECTOR', glName(auxCount), 'RULENAME', RULE_NAME), 1);
9320 PACK;
9321 WHEN CZ_R_OPTIONAL_INSIDE THEN
9322 --'Rule ''%RULENAME'' cannot be generated because the node ''%NODENAME'' is a descendant of the optional
9323 -- component ''%COMPONENT'' inside the connected model ''%CONNECTOR'', and therefore cannot participate
9324 -- in rules. Rule ignored.'
9325 REPORT(CZ_UTILS.GET_TEXT('CZ_R_OPTIONAL_INSIDE', 'NODENAME', localString, 'COMPONENT', glName(auxIndex), 'CONNECTOR', glName(auxCount), 'RULENAME', RULE_NAME), 1);
9326 PACK;
9327 WHEN CZ_R_OPTIONAL_ASIDE THEN
9328 --'Rule ''%RULENAME'' cannot be generated because it relates the multiply instantiable component ''%COMPONENT1''
9329 -- with the optional component ''%COMPONENT2''. Rule ignored.'
9330 REPORT(CZ_UTILS.GET_TEXT('CZ_R_OPTIONAL_ASIDE', 'COMPONENT1', glName(auxIndex), 'COMPONENT2', glName(auxCount), 'RULENAME', RULE_NAME), 1);
9331 PACK;
9332 WHEN CZ_R_CONNECTOR_ASIDE THEN
9333 --'Rule ''%RULENAME'' cannot be generated because it relates the multiply instantiable component ''%COMPONENT''
9334 -- with the connected model ''%CONNECTOR''. Rule ignored.'
9335 REPORT(CZ_UTILS.GET_TEXT('CZ_R_CONNECTOR_ASIDE', 'COMPONENT', glName(auxIndex), 'CONNECTOR', glName(auxCount), 'RULENAME', RULE_NAME), 1);
9336 PACK;
9337 WHEN CZ_R_CONFLICTING_NODES THEN
9338 --'Logic cannot be generated for Rule ''%RULENAME''. This is because the rule participants are descendants of
9339 -- Components ''%COMPONENT1'' and ''%COMPONENT2'' that can be instantiated multiple times. Rule ignored.'
9340 REPORT(CZ_UTILS.GET_TEXT('CZ_R_CONFLICTING_NODES', 'COMPONENT1', glName(auxIndex), 'COMPONENT2', glName(auxCount), 'RULENAME', RULE_NAME), 1);
9341 PACK;
9342 WHEN CZ_R_INCORRECT_NODE_LEVEL THEN
9343 --'Rule ''%RULENAME'' cannot be generated because it relates the multiply instantiable component ''%COMPONENT1'' with the component ''%COMPONENT2''.
9344 -- Rule ignored.'
9345 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCORRECT_NODE_LEVEL', 'COMPONENT1', glName(auxIndex), 'COMPONENT2', glName(auxCount), 'RULENAME', RULE_NAME), 1);
9346 PACK;
9347 WHEN CZ_R_ACROSS_TRACKABLE THEN
9348 --'Logic cannot be generated for rule ''%RULENAME'' because it relates a trackable instantiable Model with
9349 -- non-trackable items inside the Container Model ''%PROJECTNAME''. Rule ignored.'
9350 REPORT(CZ_UTILS.GET_TEXT('CZ_R_ACROSS_TRACKABLE', 'PROJECTNAME', rootProjectName, 'RULENAME', RULE_NAME), 1);
9351 PACK;
9352 WHEN CZ_R_CONNECTOR_RULE THEN
9353 --'Rule ''%RULENAME'' in the Model ''%MODELNAME'' is invalid. Connectors cannot participate in rules.'
9354 REPORT(CZ_UTILS.GET_TEXT('CZ_R_CONNECTOR_RULE', 'MODELNAME', thisProjectName, 'RULENAME', RULE_NAME), 1);
9355 PACK;
9356 WHEN CZ_R_INVALID_LOGIC_RULE THEN
9357 --'Invalid logic rule, rule ''%RULENAME'' ignored'
9358 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INVALID_LOGIC_RULE', 'RULENAME', RULE_NAME), 1);
9359 PACK;
9360 WHEN CZ_R_INCOMPLETE_LOGIC_RULE THEN
9361 --'Incomplete logic rule, rule ''%RULENAME'' ignored'
9362 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCOMPLETE_LOGIC_RULE', 'RULENAME', RULE_NAME), 1);
9363 PACK;
9364 WHEN CZ_R_LOGIC_RULE_WRONG_FEAT THEN
9365 --'Incorrect feature type in logic rule, feature ''%FEATNAME'', rule ''%RULENAME'' ignored'
9366 REPORT(CZ_UTILS.GET_TEXT('CZ_R_LOGIC_RULE_WRONG_FEAT', 'FEATNAME', localString, 'RULENAME', RULE_NAME), 1);
9367 PACK;
9368 WHEN CZ_R_NUMERIC_RULE_WRONG_FEAT THEN
9369 --'Incorrect feature type in numeric rule, feature ''%FEATNAME'', rule ''%RULENAME'' ignored'
9370 REPORT(CZ_UTILS.GET_TEXT('CZ_R_NUMERIC_RULE_WRONG_FEAT', 'FEATNAME', localString, 'RULENAME', RULE_NAME), 1);
9371 PACK;
9372 WHEN CZ_R_INCORRECT_FEATURE_TYPE THEN
9373 --'Text features are not allowed to participate in rules, feature ''%FEATNAME'', rule ''%RULENAME'' ignored.'
9374 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCORRECT_FEATURE_TYPE', 'FEATNAME', localString, 'RULENAME', RULE_NAME), 1);
9375 PACK;
9376 WHEN CZ_R_INVALID_NUMERIC_RULE THEN
9377 --'Invalid numeric rule, rule ''%RULENAME'' ignored'
9378 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INVALID_NUMERIC_RULE', 'RULENAME', RULE_NAME), 1);
9379 PACK;
9380 WHEN CZ_R_INCORRECT_NUMERIC_RHS THEN
9381 --'The node ''%NODENAME'' in the Model ''%MODELNAME'' is a(n) ''%NODETYPE''. This type of node cannot be
9382 -- a participant on the B side of a Numeric rule. Rule ''%RULENAME'' ignored.'
9383 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCORRECT_NUMERIC_RHS', 'NODENAME', localString, 'MODELNAME', thisProjectName, 'NODETYPE', errorMessage, 'RULENAME', RULE_NAME), 1);
9384 PACK;
9385 WHEN CZ_R_INCOMPATIBLE_SYSPROP THEN
9386 --'The Property ''%PROPERTYNAME'' is invalid for the node ''%NODENAME''. Rule ''%RULENAME'' in Model ''%MODELNAME'' ignored.'
9387 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCOMPATIBLE_SYSPROP', 'PROPERTYNAME', localString, 'NODENAME', glName(auxIndex), 'MODELNAME', thisProjectName, 'RULENAME', RULE_NAME), 1);
9388 PACK;
9389 WHEN CZ_R_INVALID_COMPARISON_RULE THEN
9390 --'Invalid comparison rule, rule ''%RULENAME'' ignored'
9391 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INVALID_COMPARISON_RULE', 'RULENAME', RULE_NAME), 1);
9392 PACK;
9393 WHEN CZ_R_INVALID_NUMERIC_PART THEN
9394 --'Invalid numeric part, rule ''%RULENAME'' ignored'
9395 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INVALID_NUMERIC_PART', 'RULENAME', RULE_NAME), 1);
9396 PACK;
9397 WHEN CZ_R_INCOMPLETE_NUMERIC_RULE THEN
9398 --'Incomplete numeric rule, rule ''%RULENAME'' ignored'
9399 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCOMPLETE_NUMERIC_RULE', 'RULENAME', RULE_NAME), 1);
9400 PACK;
9401 WHEN CZ_R_INVALID_NUMRULE_NODE THEN
9402 --'Invalid numeric rule node, rule ''%RULENAME'' ignored'
9403 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INVALID_NUMRULE_NODE', 'RULENAME', RULE_NAME), 1);
9404 PACK;
9405 WHEN CZ_R_INVALID_NUM_SIMPLE_EXPR THEN
9406 --'The left-hand side expression must have a root rounding operator, rule ''%RULENAME'' ignored'
9407 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INVALID_NUM_SIMPLE_EXPR', 'RULENAME', RULE_NAME), 1);
9408 PACK;
9409 WHEN CZ_E_UNKNOWN_EXPR_TYPE THEN
9410 --'Unknown expression type, rule ''%RULENAME'' ignored'
9411 REPORT(CZ_UTILS.GET_TEXT('CZ_E_UNKNOWN_EXPR_TYPE', 'RULENAME', RULE_NAME), 1);
9412 PACK;
9413 WHEN CZ_E_WRONG_ARITHMETIC_OPER THEN
9414 --'Incorrect arithmetic operator, rule ''%RULENAME'' ignored'
9415 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_ARITHMETIC_OPER', 'RULENAME', RULE_NAME), 1);
9416 PACK;
9417 WHEN CZ_E_WRONG_COMPARISON_OPER THEN
9418 --'Incorrect comparison operator, rule ''%RULENAME'' ignored'
9419 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_COMPARISON_OPER', 'RULENAME', RULE_NAME), 1);
9420 PACK;
9421 WHEN CZ_E_WRONG_ROUND_OPERATOR THEN
9422 --'Incorrect ROUND operator, rule ''%RULENAME'' ignored'
9423 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_ROUND_OPERATOR', 'RULENAME', RULE_NAME), 1);
9424 PACK;
9425 WHEN CZ_E_WRONG_ANDOR_OPERATOR THEN
9426 --'Incorrect AND/OR operator, rule ''%RULENAME'' ignored'
9427 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_ANDOR_OPERATOR', 'RULENAME', RULE_NAME), 1);
9428 PACK;
9429 WHEN CZ_E_WRONG_NOT_OPERATOR THEN
9430 --'Incorrect NOT operator, rule ''%RULENAME'' ignored'
9431 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_NOT_OPERATOR', 'RULENAME', RULE_NAME), 1);
9432 PACK;
9433 WHEN CZ_E_WRONG_NOTTRUE_OPERATOR THEN
9434 --'Incorrect NOTTRUE operator, rule ''%RULENAME'' ignored'
9435 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_NOTTRUE_OPERATOR', 'RULENAME', RULE_NAME), 1);
9436 PACK;
9437 WHEN CZ_E_WRONG_VAL_EXPRESSION THEN
9438 --'Incorrect VAL expression, rule ''%RULENAME'' ignored'
9439 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_VAL_EXPRESSION', 'RULENAME', RULE_NAME), 1);
9440 PACK;
9441 WHEN CZ_E_WRONG_VAL_EXPRESS_TYPE THEN
9442 --'Incorrect VAL expression type, rule ''%RULENAME'' ignored'
9443 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_VAL_EXPRESS_TYPE', 'RULENAME', RULE_NAME), 1);
9444 PACK;
9445 WHEN CZ_E_WRONG_MINMAX_OPERATOR THEN
9446 --'Incorrect MIN/MAX operator, rule ''%RULENAME'' ignored'
9447 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_MINMAX_OPERATOR', 'RULENAME', RULE_NAME), 1);
9448 PACK;
9449 WHEN CZ_E_WRONG_OF_OPERATOR THEN
9450 --'Incorrect OF operator, rule ''%RULENAME'' ignored'
9451 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_OF_OPERATOR', 'RULENAME', RULE_NAME), 1);
9452 PACK;
9453 WHEN CZ_E_WRONG_DOT_OPERATOR THEN
9454 --'Incorrect DOT operator, rule ''%RULENAME'' ignored'
9455 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_DOT_OPERATOR', 'RULENAME', RULE_NAME), 1);
9456 PACK;
9457 WHEN CZ_E_DOT_TYPE_MISMATCH THEN
9458 --'DOT type mismatch, rule ''%RULENAME'' ignored'
9459 REPORT(CZ_UTILS.GET_TEXT('CZ_E_DOT_TYPE_MISMATCH', 'RULENAME', RULE_NAME), 1);
9460 PACK;
9461 WHEN CZ_E_BAD_PROPERTY_TYPE THEN
9462 --'Bad property type, rule ''%RULENAME'' ignored'
9463 REPORT(CZ_UTILS.GET_TEXT('CZ_E_BAD_PROPERTY_TYPE', 'RULENAME', RULE_NAME), 1);
9464 PACK;
9465 WHEN CZ_E_NO_SUCH_PROPERTY THEN
9466 --'No such property, rule ''%RULENAME'' ignored'
9467 REPORT(CZ_UTILS.GET_TEXT('CZ_E_NO_SUCH_PROPERTY', 'RULENAME', RULE_NAME), 1);
9468 PACK;
9469 WHEN CZ_E_NULL_PROPERTY_VALUE THEN
9470 --'Null property value, rule ''%RULENAME'' ignored'
9471 REPORT(CZ_UTILS.GET_TEXT('CZ_E_NULL_PROPERTY_VALUE', 'RULENAME', RULE_NAME), 1);
9472 PACK;
9473 WHEN CZ_E_INCORRECT_PROPERTY THEN
9474 --'Unable to identify property value, rule ''%RULENAME'' ignored'
9475 REPORT(CZ_UTILS.GET_TEXT('CZ_E_INCORRECT_PROPERTY', 'RULENAME', RULE_NAME), 1);
9476 PACK;
9477 WHEN CZ_E_UNKNOWN_OPERATOR_TYPE THEN
9478 --'Unknown operator type, type %OPERTYPE, rule ''%RULENAME'' ignored'
9479 REPORT(CZ_UTILS.GET_TEXT('CZ_E_UNKNOWN_OPERATOR_TYPE', 'OPERTYPE', TO_CHAR(nParam), 'RULENAME', RULE_NAME), 1);
9480 PACK;
9481 WHEN CZ_E_INVALID_OPERAND_TYPE THEN
9482 --'Invalid operand type, operator ''%OPERNAME'', rule ''%RULENAME'' ignored'
9483 REPORT(CZ_UTILS.GET_TEXT('CZ_E_INVALID_OPERAND_TYPE', 'OPERNAME', LTRIM(RTRIM(OperatorLiterals(v_tExprSubtype(nParam)))), 'RULENAME', RULE_NAME), 1);
9484 PACK;
9485 WHEN CZ_E_MATH_PARAMETERS THEN
9486 --'Incorrect number of parameters to mathematical function %FUNCTION, rule ''%RULENAME'' ignored'
9487 REPORT(CZ_UTILS.GET_TEXT('CZ_E_MATH_PARAMETERS', 'RULENAME', RULE_NAME, 'FUNCTION', LTRIM(RTRIM(OperatorLiterals(nParam)))), 1);
9488 PACK;
9489 WHEN CZ_E_INCORRECT_POWER THEN
9490 --'Exponent value of a POW function could not be resolved to a constant integer, rule ''%RULENAME'' ignored'
9491 REPORT(CZ_UTILS.GET_TEXT('CZ_E_INCORRECT_POWER', 'RULENAME', RULE_NAME), 1);
9492 PACK;
9493 WHEN CZ_R_UNABLE_TO_CREATE_TABLE THEN
9494 --'Unable to create a temporary table for property-based compatibility rule, rule ''%RULENAME'' ignored, error: %ERRORTEXT'
9495 REPORT(CZ_UTILS.GET_TEXT('CZ_R_UNABLE_TO_CREATE_TABLE', 'RULENAME', RULE_NAME, 'ERRORTEXT', errorMessage), 1);
9496 PACK;
9497 WHEN CZ_R_WRONG_COMPAT_EXPRESSION THEN
9498 --'Incorrect compatibility expression, rule ''%RULENAME'' ignored'
9499 REPORT(CZ_UTILS.GET_TEXT('CZ_R_WRONG_COMPAT_EXPRESSION', 'RULENAME', RULE_NAME), 1);
9500 PACK;
9501 WHEN CZ_E_WRONG_OPER_IN_COMPAT THEN
9502 --'Incorrect operator in compatibility rule, rule ''%RULENAME'' ignored'
9503 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_OPER_IN_COMPAT', 'RULENAME', RULE_NAME), 1);
9504 PACK;
9505 WHEN CZ_E_UKNOWN_OPER_IN_COMPAT THEN
9506 --'Unknown operator in compatibility rule, rule ''%RULENAME'' ignored'
9507 REPORT(CZ_UTILS.GET_TEXT('CZ_E_UKNOWN_OPER_IN_COMPAT', 'RULENAME', RULE_NAME), 1);
9508 PACK;
9509 WHEN CZ_R_COMPAT_NO_COMBINATIONS THEN
9510 --'No valid combinations, rule ''%RULENAME'' ignored'
9511 REPORT(CZ_UTILS.GET_TEXT('CZ_R_COMPAT_NO_COMBINATIONS', 'RULENAME', RULE_NAME), 1);
9512 PACK;
9513 WHEN CZ_R_WRONG_EXPRESSION_NODE THEN
9514 --'Incorrect node in expression, rule ''%RULENAME'' ignored'
9515 REPORT(CZ_UTILS.GET_TEXT('CZ_R_WRONG_EXPRESSION_NODE', 'RULENAME', RULE_NAME), 1);
9516 PACK;
9517 WHEN CZ_R_NO_DEFINING_SELECTION THEN
9518 --'No selection made between primary and defining feature in design chart rule, rule ''%RULENAME'' ignored'
9519 REPORT(CZ_UTILS.GET_TEXT('CZ_R_NO_DEFINING_SELECTION', 'RULENAME', RULE_NAME), 1);
9520 PACK;
9521 WHEN CZ_R_NO_PRIMARY_FEATURE THEN
9522 --'No primary feature in design chart rule, rule ''%RULENAME'' ignored'
9523 REPORT(CZ_UTILS.GET_TEXT('CZ_R_NO_PRIMARY_FEATURE', 'RULENAME', RULE_NAME), 1);
9524 PACK;
9525 WHEN CZ_R_DELETED_OPTION THEN
9526 --'The Model structure has changed and the Design Chart rule ''%RULENAME'' now contains deleted node ''%NODENAME''.
9527 -- The rule will be ignored.'
9528 REPORT(CZ_UTILS.GET_TEXT('CZ_R_DELETED_OPTION', 'RULENAME', RULE_NAME, 'NODENAME', errorMessage), 1);
9529 PACK;
9530 WHEN CZ_R_WRONG_DESIGNCHART_RULE THEN
9531 --'No one-to-one correspondence between options of primary and defining feature in design chart rule, rule ''%RULENAME'' ignored'
9532 REPORT(CZ_UTILS.GET_TEXT('CZ_R_WRONG_DESIGNCHART_RULE', 'RULENAME', RULE_NAME), 1);
9533 PACK;
9534 WHEN CZ_R_DUPLICATE_COMBINATION THEN
9535 --'Not unique combination of defining feature options for a primary option in design chart rule, rule ''%RULENAME'' ignored'
9536 REPORT(CZ_UTILS.GET_TEXT('CZ_R_DUPLICATE_COMBINATION', 'RULENAME', RULE_NAME), 1);
9537 PACK;
9538 WHEN CZ_R_INCOMPLETE_DES_CHART THEN
9539 --'Incorrect number of compatibility selections made for the option ''%OPTIONNAME'' of the Primary Feature ''%FEATURENAME''
9540 -- in Design Chart ''%RULENAME''. Rule ignored.'
9541 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCOMPLETE_DES_CHART', 'OPTIONNAME', glName(auxIndex), 'FEATURENAME', glName(auxCount), 'RULENAME', RULE_NAME), 1);
9542 PACK;
9543 WHEN CZ_R_EMPTY_COMPAT_RULE THEN
9544 --'Empty compatibility rule, rule ''%RULENAME'' ignored'
9545 REPORT(CZ_UTILS.GET_TEXT('CZ_R_EMPTY_COMPAT_RULE', 'RULENAME', RULE_NAME), 1);
9546 PACK;
9547 WHEN CZ_R_COMPAT_SINGLE_FEATURE THEN
9548 --'Compatibility rule must have at least two participating features, rule ''%RULENAME'' ignored'
9549 REPORT(CZ_UTILS.GET_TEXT('CZ_R_COMPAT_SINGLE_FEATURE', 'RULENAME', RULE_NAME), 1);
9550 PACK;
9551 WHEN CZ_R_COMPAT_RULE_NO_PROPERTY THEN
9552 --'Incomplete compatibility rule, no property defined for feature ''%FEATNAME'', rule ''%RULENAME'' ignored'
9553 REPORT(CZ_UTILS.GET_TEXT('CZ_R_COMPAT_RULE_NO_PROPERTY', 'FEATNAME', glName(glIndexByPsNodeId(v_tExprPsNodeId(nParam))), 'RULENAME', RULE_NAME), 1);
9554 PACK;
9555 WHEN CZ_R_OPTION_NO_PROPERTY THEN
9556 --'Property value for ''%PROPERTYNAME'' is not defined for item ''%ITEMNAME'' with parent ''%PARENTNAME'' in model ''%MODELNAME''. Rule ''%RULENAME'' ignored.'
9557 REPORT(CZ_UTILS.GET_TEXT('CZ_R_OPTION_NO_PROPERTY', 'PROPERTYNAME', errorMessage, 'ITEMNAME', glName(auxIndex), 'PARENTNAME', glName(nParam), 'MODELNAME', glName(glIndexByPsNodeId(inProjectId)),'RULENAME', RULE_NAME), 1);
9558 PACK;
9559 WHEN CZ_R_LONG_PROPERTY_VALUE THEN
9560 --'Value of the Property ''%PROPERTYNAME'' is too long for item ''%ITEMNAME'' with parent ''%PARENTNAME'' in model ''%MODELNAME''. Rule ''%RULENAME'' ignored.'
9561 REPORT(CZ_UTILS.GET_TEXT('CZ_R_LONG_PROPERTY_VALUE', 'PROPERTYNAME', errorMessage, 'ITEMNAME', glName(auxIndex), 'PARENTNAME', glName(nParam), 'MODELNAME', glName(glIndexByPsNodeId(inProjectId)),'RULENAME', RULE_NAME), 1);
9562 PACK;
9563 WHEN CZ_R_INCORRECT_DATA_TYPE THEN
9564 --'Incorrect data: integer or decimal property ''%PROPERTYNAME'' has a text value of ''%VALUE''. Rule ''%RULENAME'' in model ''%MODELNAME'' ignored.'
9565 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCORRECT_DATA_TYPE', 'PROPERTYNAME', errorMessage, 'VALUE', localString, 'MODELNAME', glName(glIndexByPsNodeId(inProjectId)), 'RULENAME', RULE_NAME), 1);
9566 PACK;
9567 WHEN CZ_R_INCORRECT_NUMERICLHS THEN
9568 --'''%PROPERTYNAME'' is invalid in the Numeric rule ''%RULENAME'' in Model ''%MODELNAME''. Text and Boolean Properties
9569 -- cannot be participants on the left-hand side of a Numeric rule. Rule ignored.'
9570 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCORRECT_NUMERICLHS', 'PROPERTYNAME', errorMessage, 'MODELNAME', glName(glIndexByPsNodeId(inProjectId)), 'RULENAME', RULE_NAME), 1);
9571 PACK;
9572 WHEN CZ_R_PROPERTY_NOT_ALLOWED THEN
9573 --'The expression contained a Text property which is only allowed in a comparison expression. A Text property is not
9574 -- allowed in the context of your expression. Rule ''%RULENAME'' in Model ''%MODELNAME'' ignored.'
9575 REPORT(CZ_UTILS.GET_TEXT('CZ_R_PROPERTY_NOT_ALLOWED', 'MODELNAME', glName(glIndexByPsNodeId(inProjectId)), 'RULENAME', RULE_NAME), 1);
9576 PACK;
9577 WHEN CZ_R_VIRTUAL_COMPONENT THEN
9578 --'The system property ''%PROPERTYNAME'' is not allowed because ''%NODENAME'' is required. Refer to Oracle Configurator
9579 -- Developer documentation for details. Rule ''%RULENAME'' ignored.'
9580 REPORT(CZ_UTILS.GET_TEXT('CZ_R_VIRTUAL_COMPONENT', 'PROPERTYNAME', localString, 'NODENAME', glName(nParam), 'RULENAME', RULE_NAME), 1);
9581 PACK;
9582 WHEN CZ_R_WRONG_COMPAT_TABLE THEN
9583 --'Incorrect explicit compatibility table, rule ''%RULENAME'' ignored'
9584 REPORT(CZ_UTILS.GET_TEXT('CZ_R_WRONG_COMPAT_TABLE', 'RULENAME', RULE_NAME), 1);
9585 PACK;
9586 WHEN CZ_R_NO_PARTICIPANTS THEN
9587 --'Incomplete rule - no participants, rule ''%RULENAME'' ignored'
9588 REPORT(CZ_UTILS.GET_TEXT('CZ_R_NO_PARTICIPANTS', 'RULENAME', RULE_NAME), 1);
9589 PACK;
9590 WHEN CZ_R_NO_COMPONENT_ID THEN
9591 --'No ps_node_id defined for none of the rule participants, rule ''%RULENAME'' ignored'
9592 REPORT(CZ_UTILS.GET_TEXT('CZ_R_NO_COMPONENT_ID', 'RULENAME', RULE_NAME), 1);
9593 PACK;
9594 WHEN CZ_R_RULE_WRONG_EXPRESSION THEN
9595 --'Invalid expression specified, rule ''%RULENAME'' ignored'
9596 REPORT(CZ_UTILS.GET_TEXT('CZ_R_RULE_WRONG_EXPRESSION', 'RULENAME', RULE_NAME), 1);
9597 PACK;
9598 WHEN CZ_R_WRONG_EFFECTIVITY_SET THEN
9599 --'Invalid effectivity set assosiated with rule ''%RULENAME'', rule ignored'
9600 REPORT(CZ_UTILS.GET_TEXT('CZ_R_WRONG_EFFECTIVITY_SET', 'RULENAME', RULE_NAME), 1);
9601 PACK;
9602 WHEN CZ_R_LITERAL_NO_VALUE THEN
9603 --'No literal value specified in rule ''%RULENAME'', rule ignored'
9604 REPORT(CZ_UTILS.GET_TEXT('CZ_R_LITERAL_NO_VALUE', 'RULENAME', RULE_NAME), 1);
9605 PACK;
9606 WHEN CZ_R_INCORRECT_NODE_ID THEN
9607 --'Incomplete or invalid data in rule ''%RULENAME'', rule ignored'
9608 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCORRECT_NODE_ID', 'RULENAME', RULE_NAME), 1);
9609 PACK;
9610 WHEN CZ_R_FEATURE_NO_PROPERTY THEN
9611 --'Invalid property or no property specified in rule ''%RULENAME'', rule ignored'
9612 REPORT(CZ_UTILS.GET_TEXT('CZ_R_FEATURE_NO_PROPERTY', 'RULENAME', RULE_NAME), 1);
9613 PACK;
9614 WHEN CZ_R_INCORRECT_REFERENCE THEN
9615 --'The reference %PATH is invalid. At least one node does not exist in the Model or is not effective when the rule is effective.
9616 -- Rule ''%RULENAME'' ignored.'
9617 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCORRECT_REFERENCE', 'PATH', localString, 'RULENAME', RULE_NAME), 1);
9618 PACK;
9619 WHEN CZ_R_AMBIGUOUS_REFERENCE THEN
9620 --'Unable to resolve Model node reference %PATH because it is ambiguous. Rule ''%RULENAME'' ignored.'
9621 REPORT(CZ_UTILS.GET_TEXT('CZ_R_AMBIGUOUS_REFERENCE', 'PATH', localString, 'RULENAME', RULE_NAME), 1);
9622 PACK;
9623 WHEN CZ_E_NO_EXPECTED_CHILDREN THEN
9624 --'Node ''%NODENAME'' has no children, rule ''%RULENAME'' ignored'
9625 REPORT(CZ_UTILS.GET_TEXT('CZ_E_NO_EXPECTED_CHILDREN', 'NODENAME', localString, 'RULENAME', RULE_NAME), 1);
9626 PACK;
9627 WHEN CZ_E_NO_OPTIONAL_CHILDREN THEN
9628 --'All children of the BOM node ''%NODENAME'' are required when parent is selected, no optional children, rule ''%RULENAME'' ignored'
9629 REPORT(CZ_UTILS.GET_TEXT('CZ_E_NO_OPTIONAL_CHILDREN', 'NODENAME', localString, 'RULENAME', RULE_NAME), 1);
9630 PACK;
9631 WHEN CZ_R_TRACKABLE_ANCESTOR THEN
9632 --'BOM item ''%ITEMNAME'' cannot participate in the Numeric rule ''%RULENAME'' because it contains other trackable BOM items.'
9633 REPORT(CZ_UTILS.GET_TEXT('CZ_R_TRACKABLE_ANCESTOR', 'ITEMNAME', glName(nParam), 'RULENAME', RULE_NAME), 1);
9634 PACK;
9635 WHEN CZ_R_AGAINST_TRACKABLE THEN
9636 --'Numeric rule ''%RULENAME'' is invalid. In a Container Model, a Numeric rule cannot contribute to or consume
9637 -- from how many instances of a trackable Model are allowed at runtime.'
9638 REPORT(CZ_UTILS.GET_TEXT('CZ_R_AGAINST_TRACKABLE', 'RULENAME', RULE_NAME), 1);
9639 PACK;
9640 --'Only nontranslatable System Properties are allowed in the WHERE clause of a COMPATIBLE or FORALL operator.
9641 -- The System Property ''%PROPERTYNAME'' can be translated, therefore it is invalid in this context. Rule ''%RULENAME''
9642 -- in the Model ''%MODELNAME'' will be ignored.'
9643 WHEN CZ_E_DESCRIPTION_IN_WHERE THEN
9644 REPORT(CZ_UTILS.GET_TEXT('CZ_E_DESCRIPTION_IN_WHERE', 'PROPERTYNAME', errorMessage,'MODELNAME', thisProjectName, 'RULENAME', RULE_NAME), 1);
9645 PACK;
9646 --'Only static System Properties are allowed in the WHERE clause of a COMPATIBLE or FORALL operator. The value of the
9647 -- System Property ''%PROPERTYNAME'' can change at runtime, therefore it is invalid in this context. Rule ''%RULENAME''
9648 -- in the Model ''%MODELNAME'' will be ignored.'
9649 WHEN CZ_E_PROPERTY_NOT_STATIC THEN
9650 REPORT(CZ_UTILS.GET_TEXT('CZ_E_PROPERTY_NOT_STATIC', 'PROPERTYNAME', errorMessage,'MODELNAME', thisProjectName, 'RULENAME', RULE_NAME), 1);
9651 PACK;
9652 WHEN CZ_R_TEMPLATE_UNKNOWN OR CZ_R_EMPTY_PARAMETER_SCOPE OR CZ_R_PARAMETER_NOT_FOUND OR
9653 CZ_R_TYPE_NO_PROPERTY OR CZ_R_NO_SIGNATURE_ID THEN
9654 --'Unable to generate rule ''%RULENAME'', internal data error.'
9655 REPORT(CZ_UTILS.GET_TEXT('CZ_G_INTERNAL_RULE_ERROR', 'RULENAME', RULE_NAME), 1);
9656 PACK;
9657 WHEN CZ_G_INVALID_RULE_EXPLOSION THEN
9658 --This is fatal: model_ref_expl_id of one of the participants references an explosion table
9659 --other than the current model table
9660 errorMessage := RULE_NAME;
9661 IF(StopOnFatalRuleError = 1)THEN
9662 IF(c_rules%ISOPEN)THEN CLOSE c_rules; END IF;
9663 RAISE;
9664 ELSE
9665 --'Unable to generate rule ''%RULENAME'', internal data error.'
9666 REPORT(CZ_UTILS.GET_TEXT('CZ_G_INTERNAL_RULE_ERROR', 'RULENAME', errorMessage), 1);
9667 PACK;
9668 END IF;
9669 WHEN CZ_R_UNABLE_TO_CREATE_HEADER THEN
9670
9671 --This is supposed to be a definitely fatal error, so raise the exception.
9672
9673 IF(c_rules%ISOPEN)THEN CLOSE c_rules; END IF;
9674 RAISE;
9675 WHEN CZ_LCE_CONTINUE THEN
9676 --This exception is used to immediately move to the next loop, not an error.
9677 NULL;
9678 WHEN OTHERS THEN
9679 IF(nDebug >= 40 AND nDebug <= 54)THEN
9680 errorMessage := RULE_NAME;
9681 ELSIF(SUBSTR(TO_CHAR(nDebug), 1, 1) = '8')THEN
9682 errorMessage := TO_CHAR(nRuleId);
9683 END IF;
9684
9685 --When the first data corruption-type error for a rule is encountered, logic gen stops.
9686 --However, it may be convenient for debugging purposes to be able to report all of such
9687 --rules. So, check the db setting here.
9688
9689 IF(StopOnFatalRuleError = 1)THEN
9690 IF(c_rules%ISOPEN)THEN CLOSE c_rules; END IF;
9691 RAISE;
9692 ELSE
9693 --'Unable to generate rule ''%RULENAME'', internal error %ERRORTEXT'
9694 REPORT(CZ_UTILS.GET_TEXT('CZ_G_GENERAL_RULE_ERROR', 'RULENAME', RULE_NAME, 'ERRORTEXT', SQLERRM), 1);
9695 PACK;
9696 END IF;
9697 END;
9698 END LOOP;
9699 CLOSE c_rules;
9700
9701 --Now generate the INC relations into the root rule file for the non-virtual components
9702 --that have rules against their max.
9703
9704 IF(v_MaxRuleExists.COUNT > 0)THEN
9705 IF(v_tIsHeaderGenerated.EXISTS(thisComponentExplId))THEN
9706
9707 --Use this header to generate the rule into
9708
9709 nHeaderId := v_tIsHeaderGenerated(thisComponentExplId);
9710
9711 ELSE
9712
9713 nHeaderId := next_lce_header_id;
9714
9715 BEGIN
9716
9717 --Insert the rule net logic header record into the table
9718
9719 INSERT INTO cz_lce_headers
9720 (lce_header_id, gen_version, gen_header, component_id, net_type,
9721 devl_project_id, model_ref_expl_id, nbr_required_expls, deleted_flag)
9722 VALUES
9723 (nHeaderId, VersionString, GenHeader, inComponentId, LOGIC_NET_TYPE_MANDATORY,
9724 thisProjectId, thisComponentExplId, 1, FLAG_PENDING);
9725
9726 INSERT INTO cz_lce_load_specs
9727 (attachment_expl_id, lce_header_id, required_expl_id, attachment_comp_id,
9728 model_id, net_type, deleted_flag)
9729 VALUES
9730 (thisComponentExplId, nHeaderId, thisComponentExplId, inComponentId,
9731 thisProjectId, LOGIC_NET_TYPE_MANDATORY, FLAG_PENDING);
9732
9733 EXCEPTION
9734 WHEN OTHERS THEN
9735 errorMessage := SQLERRM;
9736 RAISE CZ_R_UNABLE_TO_CREATE_HEADER;
9737 END;
9738
9739 NewHeaders(counterNewHeaders) := nHeaderId;
9740 NewHeadersComponents(counterNewHeaders) := inComponentId;
9741 NewHeadersExplosions(counterNewHeaders) := thisComponentExplId;
9742 counterNewHeaders := counterNewHeaders + 1;
9743
9744 v_tIsHeaderGenerated(thisComponentExplId) := nHeaderId;
9745 v_tSequenceNbr(nHeaderId) := 1;
9746 v_tLogicNetType(nHeaderId) := LOGIC_NET_TYPE_MANDATORY;
9747 nNewLogicFileFlag := 1;
9748
9749 END IF;
9750
9751 --If the logic file has changed then we need to flush off the buffer
9752
9753 IF(nHeaderId <> nPreviousHeaderId)THEN
9754
9755 IF(vLogicText IS NOT NULL)THEN
9756 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
9757 (nPreviousHeaderId, v_tSequenceNbr(nPreviousHeaderId), vLogicText);
9758 vLogicText := NULL;
9759 v_tSequenceNbr(nPreviousHeaderId) := v_tSequenceNbr(nPreviousHeaderId) + 1;
9760 END IF;
9761
9762 END IF;
9763
9764 IF(nNewLogicFileFlag = 1)THEN
9765
9766 --This is a new logic file, put the header lines in
9767
9768 vLogicLine := 'CONTROL NOSPEC' || NewLine || 'VERSION 3 3' || NewLine || NewLine ||
9769 'REM -- Rules file for component: ' || TO_CHAR(inComponentId) ||
9770 ', explosion node: ' || TO_CHAR(thisComponentExplId) || NewLine || NewLine ||
9771 'EFF , , ' || NewLine || NewLine;
9772 PACK;
9773 END IF;
9774
9775 FOR i IN 1..v_NodeId.COUNT LOOP
9776 IF(v_MaxRuleExists.EXISTS(v_NodeId(i)) AND v_tVirtualFlag(i) = FLAG_NON_VIRTUAL AND
9777 v_tNodeDepth(i) > 0)THEN
9778
9779 --Use intermediate variable instead of using NVL because this is faster
9780
9781 IF(v_tReferringId(i) IS NOT NULL)THEN
9782 localString := TO_CHAR(glPersistentId(v_tReferringId(i)));
9783 ELSE
9784 localString := TO_CHAR(glPersistentId(v_tPsNodeId(i)));
9785 END IF;
9786
9787 vLogicLine := 'INC 1 P_' || localString || '_MAX round' || NewLine;
9788 PACK;
9789
9790 END IF;
9791 END LOOP;
9792
9793 END IF;
9794
9795 nDebug := 9;
9796
9797 --Flush off the buffer after rules generation
9798
9799 IF(vLogicText IS NOT NULL)THEN
9800 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
9801 (nHeaderId, v_tSequenceNbr(nHeaderId), vLogicText);
9802 vLogicText := NULL;
9803 v_tSequenceNbr(nHeaderId) := v_tSequenceNbr(nHeaderId) + 1;
9804 END IF;
9805
9806 FOR i IN 1..temp_tables.COUNT LOOP
9807 BEGIN
9808 EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || temp_tables(i);
9809 EXECUTE IMMEDIATE 'DROP TABLE ' || temp_tables(i);
9810 EXCEPTION
9811 WHEN OTHERS THEN
9812 IF(SQLCODE <> ORACLE_OBJECT_IN_USE)THEN RAISE; END IF;
9813 END;
9814 END LOOP;
9815
9816 IF(TwoPhaseCommit = 0)THEN COMMIT; END IF;
9817
9818 EXCEPTION
9819 WHEN OTHERS THEN
9820 FOR i IN 1..temp_tables.COUNT LOOP
9821 BEGIN
9822 EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || temp_tables(i);
9823 EXECUTE IMMEDIATE 'DROP TABLE ' || temp_tables(i);
9824 EXCEPTION
9825 WHEN OTHERS THEN
9826 NULL;
9827 END;
9828 END LOOP;
9829 RAISE;
9830 END; --GENERATE_RULES
9831 ---------------------------------------------------------------------------------------
9832 BEGIN --GENERATE_COMPONENT_TREE - Product Structure Generation
9833
9834 --Generate next lce_header_id for this LCE file. This is the structure net for a model or
9835 --non-virtual component.
9836
9837 nDebug := 1110000;
9838
9839 IF(inParentLogicHeaderId IS NULL)THEN
9840
9841 --If this is the root model, read and store its name and type for later use.
9842
9843 BEGIN
9844
9845 SELECT name, model_type INTO thisProjectName, thisProjectType
9846 FROM cz_devl_projects
9847 WHERE devl_project_id = inComponentId;
9848 EXCEPTION
9849 WHEN OTHERS THEN
9850 nParam := inComponentId;
9851 RAISE CZ_S_NO_SUCH_PROJECT;
9852 END;
9853
9854 IF(inComponentId = inDevlProjectId)THEN
9855
9856 --Store the name and type of the root project for which the logic generation was
9857 --originally started.
9858
9859 rootProjectName := thisProjectName;
9860 rootProjectType := thisProjectType;
9861 ELSIF(thisProjectType = MODEL_TYPE_CONTAINER_MODEL AND rootProjectType = MODEL_TYPE_CONTAINER_MODEL)THEN
9862
9863 --Container cannot be referenced or connected to.
9864
9865 errorMessage := thisProjectName;
9866 RAISE CZ_S_CONTAINER_REFERENCE;
9867 END IF;
9868 END IF;
9869
9870 IF(NOT IsLogicGenerated.EXISTS(inComponentId))THEN
9871
9872 --Read the explosions table here. It will be extensively used in rule generation. For the
9873 --structure generation, there is really no need in this table, except that now we want to
9874 --put reasonable values into CZ_LCE_HEADERS.MODEL_REF_EXPL_ID even for structure files as
9875 --this column is being made not nullable in 18.
9876
9877 IF(inParentLogicHeaderId IS NULL)THEN
9878
9879 --If this is the root model, read the table and populate project's id and explosion id
9880 --variables, and hash tables.
9881
9882 SELECT model_ref_expl_id, parent_expl_node_id, node_depth,
9883 ps_node_type, virtual_flag, component_id, referring_node_id,
9884 child_model_expl_id, expl_node_type
9885 BULK COLLECT INTO v_NodeId, v_tParentId, v_tNodeDepth,
9886 v_tNodeType, v_tVirtualFlag, v_tPsNodeId, v_tReferringId,
9887 v_tChildModelExpl, v_tExplNodeType
9888 FROM cz_model_ref_expls
9889 WHERE model_id = inComponentId AND deleted_flag = FLAG_NOT_DELETED;
9890
9891 FOR i IN 1..v_NodeId.COUNT LOOP
9892
9893 nDebug := 1110010;
9894
9895 IF(v_tVirtualFlag(i) = FLAG_NON_VIRTUAL AND v_tExplNodeType(i) = EXPL_NODE_TYPE_MANDATORY)THEN
9896
9897 --This is introduced as a remedy to a well-known type of data corruption occured during
9898 --the development process. May be removed later on when the data become stable.
9899
9900 errorMessage := thisProjectName;
9901 RAISE CZ_G_INVALID_EXPLOSION_TYPE;
9902 END IF;
9903
9904 nDebug := 1110001;
9905
9906 --Add another indexing option - by model_ref_expl_id
9907
9908 v_IndexByNodeId(v_NodeId(i)) := i;
9909
9910 --Store the explosion id and the index of the root node - the project node itself.
9911
9912 IF(v_tNodeDepth(i) = 0)THEN
9913 thisComponentExplId := v_NodeId(i);
9914 thisRootExplIndex := i;
9915 END IF;
9916
9917 --Create the EXPL_NODE_TYPE(MODEL_REF_EXPL_ID) hash table. Other explosion columns
9918 --are currently indexed through v_IndexByNodeId. Using direct hash may provide for
9919 --some performance improvement.
9920
9921 v_TypeByExplId(v_NodeId(i)) := v_tExplNodeType(i);
9922
9923 --Build the MODEL_REF_EXPL_ID(COMPONENT_ID) hash table for all the components
9924 --inside this project (not inside referenced projects). All such components
9925 --have CHILD_MODEL_EXPL_ID null. We need this table to populate MODEL_REF_EXPL_ID
9926 --in CZ_LCE_HEADERS records for structure file of this component.
9927
9928 IF(v_tChildModelExpl(i) IS NULL)THEN
9929 v_NodeIdByComponent(v_tPsNodeId(i)) := v_NodeId(i);
9930 END IF;
9931 END LOOP;
9932 ELSE
9933
9934 nDebug := 1110002;
9935
9936 --This is a non-virtual component inside this project, so the value in the
9937 --hash table exists.
9938 --We do not have to populate thisRootExplIndex, because it is used only in
9939 --rule generation and this will not be called for a non-root component.
9940 --Have to populate the other two variables though as they are used here in
9941 --the structure generation.
9942
9943 thisComponentExplId := v_NodeIdByComponent(inComponentId);
9944 END IF;
9945
9946 thisProjectId := inProjectId;
9947
9948 --Generate next lce_header_id for this LCE file. This is the structure net for a model or
9949 --non-virtual component.
9950
9951 nStructureHeaderId := next_lce_header_id;
9952
9953 BEGIN
9954
9955 --Insert the structure logic header record into the table.
9956
9957 INSERT INTO cz_lce_headers
9958 (lce_header_id, gen_version, gen_header, component_id, net_type,
9959 devl_project_id, model_ref_expl_id, nbr_required_expls, deleted_flag)
9960 VALUES
9961 (nStructureHeaderId, VersionString, GenHeader, inComponentId, LOGIC_NET_TYPE_STRUCTURE,
9962 thisProjectId, thisComponentExplId, 1, FLAG_PENDING);
9963
9964 --Insert the structure load conditions record for this component.
9965
9966 INSERT INTO cz_lce_load_specs
9967 (attachment_expl_id, lce_header_id, required_expl_id, attachment_comp_id,
9968 model_id, net_type, deleted_flag)
9969 VALUES
9970 (thisComponentExplId, nStructureHeaderId, thisComponentExplId, inComponentId,
9971 thisProjectId, LOGIC_NET_TYPE_STRUCTURE, FLAG_PENDING);
9972
9973 EXCEPTION
9974 WHEN OTHERS THEN
9975 errorMessage := SQLERRM;
9976 RAISE CZ_S_UNABLE_TO_CREATE_HEADER;
9977 END;
9978
9979 NewHeaders(counterNewHeaders) := nStructureHeaderId;
9980 NewHeadersComponents(counterNewHeaders) := inComponentId;
9981 NewHeadersExplosions(counterNewHeaders) := thisComponentExplId;
9982 counterNewHeaders := counterNewHeaders + 1;
9983
9984 ELSIF(IsLogicGenerated(inComponentId) = 0)THEN
9985
9986 --The flag may be set by two reasons: the model was considered up-to-date or the model has already been
9987 --processed in this session. Only in the first case a header should exist in the database and we need
9988 --to load it into memory. In the second case it should be in the memory and may not exist in the database.
9989 --Bug #3150226.
9990
9991 nDebug := 1110003;
9992
9993 SELECT head.lce_header_id, max(text.seq_nbr) INTO nStructureHeaderId, nSequenceNbr
9994 FROM cz_lce_headers head, cz_lce_texts text
9995 WHERE head.deleted_flag = FLAG_NOT_DELETED
9996 AND head.net_type = LOGIC_NET_TYPE_STRUCTURE
9997 AND head.component_id = inComponentId
9998 AND head.lce_header_id = text.lce_header_id
9999 GROUP BY head.lce_header_id;
10000
10001 vSeqNbrByHeader(nStructureHeaderId) := nSequenceNbr + 1;
10002 END IF;
10003
10004 nDebug := 1110004;
10005
10006 vLogicText := 'CONTROL NOSPEC' || NewLine || 'VERSION 3 3' || NewLine ||
10007 'SETDEFAULTDELTA F' || NewLine || 'EFF , , ' || NewLine || NewLine ||
10008 'REM -- Structure file for component: ' || TO_CHAR(inComponentId) || NewLine || NewLine ||
10009 'OBJECT _ALWAYS_TRUE' || NewLine || 'MINMAX 1 1 _ALWAYS_TRUE' || NewLine ||
10010 'OBJECT _ALWAYS_FALSE' || NewLine ||
10011 'GS N' || NewLine || 'GL L _ALWAYS_TRUE' || NewLine || 'GR L _ALWAYS_FALSE' || NewLine;
10012
10013 nDebug := 1110005;
10014
10015 --This SELECT statement reads the whole 'virtual' tree under a non-virtual component which also
10016 --includes the non-virtual component itself. Non-virtual components underneath are included in
10017 --order to recurse, and this function will be called for every non-virtual component underneath.
10018 --The resulting order provided by this statement is used later when generating list of options
10019 --for an option feature.
10020
10021 SELECT ps_node_id, parent_id, item_id, minimum, maximum, name, intl_text_id, minimum_selected,
10022 maximum_selected, ps_node_type, initial_value, virtual_flag, feature_type, bom_required_flag,
10023 reference_id, persistent_node_id, effective_from, effective_until, effective_usage_mask,
10024 effectivity_set_id, decimal_qty_flag, ib_trackable, accumulator_flag, initial_num_value,
10025 instantiable_flag, shippable_item_flag, inventory_transactable_flag, assemble_to_order_flag,
10026 serializable_item_flag
10027 BULK COLLECT INTO
10028 ntPsNodeId, ntParentId, ntItemId, ntMinimum, ntMaximum, ntName, ntDescriptionId, ntMinimumSel,
10029 ntMaximumSel, ntPsNodeType, ntInitialValue, ntVirtualFlag, ntFeatureType, ntBomRequired,
10030 ntReferenceId, ntPersistentId, dtEffFrom, dtEffUntil, vtUsageMask,
10031 ntEffSetId, ntDecimalQty, ntIbTrackable, ntAccumulator, ntInitialNumValue,
10032 ntInstantiableFlag, ntShippableFlag, ntTransactableFlag, ntAtoFlag, ntSerializableFlag
10033 FROM cz_ps_nodes
10034 WHERE deleted_flag = FLAG_NOT_DELETED
10035 START WITH ps_node_id = inComponentId
10036 CONNECT BY PRIOR ps_node_id = parent_id
10037 AND (PRIOR virtual_flag IS NULL OR PRIOR virtual_flag = FLAG_VIRTUAL OR
10038 PRIOR ps_node_id = inComponentId);
10039
10040 nDebug := 1110006;
10041
10042 --Make sure there is some data returned
10043
10044 IF(ntPsNodeId.LAST IS NOT NULL)THEN
10045
10046 nDebug := 1110007;
10047
10048 --Having this dummy boundary node eliminates the necessity of potentially time
10049 --consuming boundary checks during the option feature options' list generation
10050
10051 ntParentId(ntPsNodeId.LAST + 1) := NEVER_EXISTS_ID;
10052
10053 --Prepare to start the main cycle
10054
10055 i := ntPsNodeId.FIRST;
10056
10057 WHILE(i <= ntPsNodeId.LAST) LOOP --Start the main structure generating cycle
10058 BEGIN
10059
10060 CurrentlyPacking := PACKING_GENERIC;
10061
10062 --Populate the 'global' arrays - required for rules generation
10063
10064 nDebug := 1110010;
10065
10066 IF(NOT glIndexByPsNodeId.EXISTS(ntPsNodeId(i)))THEN
10067
10068 IF(ntInitialNumValue(i) IS NOT NULL)THEN ntInitialValue(i) := TO_CHAR(ntInitialNumValue(i)); END IF;
10069
10070 glPsNodeId(globalCount) := ntPsNodeId(i);
10071 glItemId(globalCount) := ntItemId(i);
10072 glPsNodeType(globalCount) := ntPsNodeType(i);
10073 glParentId(globalCount) := ntParentId(i);
10074 glFeatureType(globalCount) := ntFeatureType(i);
10075 glName(globalCount) := ntName(i);
10076 glBomRequired(globalCount) := ntBomRequired(i);
10077 glMinimum(globalCount) := ntMinimum(i);
10078 glMaximum(globalCount) := ntMaximum(i);
10079 glMinimumSel(globalCount) := ntMinimumSel(i);
10080 glMaximumSel(globalCount) := ntMaximumSel(i);
10081 glVirtualFlag(globalCount) := ntVirtualFlag(i);
10082 glInitialValue(globalCount) := ntInitialValue(i);
10083
10084 --Indexing by ps_node_id, will be used in expressions generation to get back to
10085 --the structure.
10086
10087 glIndexByPsNodeId(ntPsNodeId(i)) := globalCount;
10088
10089 --These global arrays will be indexed differently because we only need to get
10090 --persistent_node_id or reference_id by ps_node_id. Probably, good indexing
10091 --option for some of the other global arrays, too.
10092
10093 glPersistentId(ntPsNodeId(i)) := ntPersistentId(i);
10094 glReferenceId(ntPsNodeId(i)) := ntReferenceId(i);
10095 glDecimalQty(ntPsNodeId(i)) := ntDecimalQty(i);
10096 glIbTrackable(ntPsNodeId(i)) := ntIbTrackable(i);
10097 glAccumulator(ntPsNodeId(i)) := ntAccumulator(i);
10098 glInstantiableFlag(ntPsNodeId(i)) := ntInstantiableFlag(i);
10099
10100 --Children of any node start right after the node. But then, the children list may
10101 --not be dense, because children may have their own children. So in order to find
10102 --all the children of a node we need to search the whole structure after the node.
10103 --Here we store the last child's index so that we need to search not the whole
10104 --structure up to the end but up to this last child's index.
10105
10106 nDebug := 1110011;
10107
10108 IF(ntParentId(i) IS NOT NULL)THEN
10109 glLastChildIndex(ntParentId(i)) := globalCount;
10110
10111 --This array is used in design chart rules generation and contains the number of children
10112 --of a node. We actually use it only for features and BOM option classes.
10113
10114 IF(NOT featOptionsCount.EXISTS(ntParentId(i)))THEN featOptionsCount(ntParentId(i)) := 0; END IF;
10115 featOptionsCount(ntParentId(i)) := featOptionsCount(ntParentId(i)) + 1;
10116 END IF;
10117
10118 IF(ntPsNodeType(i) = PS_NODE_TYPE_BOM_STANDARD AND ntIbTrackable(i) = FLAG_IB_TRACKABLE AND
10119 thisProjectType IN (MODEL_TYPE_PTO_MODEL, MODEL_TYPE_ATO_MODEL) AND
10120 glPsNodeType(glIndexByPsNodeId(ntParentId(i))) = PS_NODE_TYPE_BOM_MODEL AND
10121 glIbTrackable(ntParentId(i)) = FLAG_NOT_IB_TRACKABLE) THEN
10122
10123 --A trackable BOM Standard item cannot be a direct child of a non-trackable
10124 --ATO/PTO Model if this model is references from any Network Container model.
10125 --Re: bug #3644036.
10126
10127 IF(NOT h_containerReferred.EXISTS(ntParentId(i)))THEN
10128
10129 BEGIN
10130
10131 EXECUTE IMMEDIATE containerReferred INTO h_containerReferred(ntParentId(i)) USING ntParentId(i);
10132
10133 EXCEPTION
10134 WHEN NO_DATA_FOUND THEN
10135 h_containerReferred(ntParentId(i)) := 0;
10136 END;
10137 END IF;
10138
10139 IF(h_containerReferred(ntParentId(i)) = 1)THEN
10140
10141 errorMessage := thisProjectName;
10142 nParam := glIndexByPsNodeId(ntPsNodeId(i));
10143 RAISE CZ_S_TRACKABLE_STANDARD;
10144 END IF;
10145 END IF;
10146
10147 --Prepare the actual effective date interval for populating global effectivity dates.
10148 --First get the nominal effective date interval either from an effectivity set or
10149 --from the local values.
10150
10151 IF(ntEffSetId(i) IS NOT NULL)THEN
10152 IF(gvIndexBySetId.EXISTS(ntEffSetId(i)))THEN
10153 CurrentEffFrom := gvEffFrom(gvIndexBySetId(ntEffSetId(i)));
10154 CurrentEffUntil := gvEffUntil(gvIndexBySetId(ntEffSetId(i)));
10155 ELSE
10156 --This is a fatal error - data corruption.
10157 --'Invalid effectivity set associated with node ''%NODENAME'''
10158 errorMessage := CZ_UTILS.GET_TEXT('CZ_S_WRONG_EFFECTIVITY_SET', 'NODENAME', ntName(i));
10159 RAISE CZ_S_WRONG_EFFECTIVITY_SET;
10160 END IF;
10161 ELSE
10162 CurrentEffFrom := dtEffFrom(i);
10163 CurrentEffUntil := dtEffUntil(i);
10164 END IF;
10165 CurrentUsageMask := vtUsageMask(i);
10166
10167 --Make sure effective dates are not null, so that actual effective date interval
10168 --will have no null bounds too. Usage mask is not null anyway.
10169
10170 IF(CurrentEffFrom IS NULL)THEN CurrentEffFrom := EpochBeginDate; END IF;
10171 IF(CurrentEffUntil IS NULL)THEN CurrentEffUntil := EpochEndDate; END IF;
10172
10173 --If this is not a model or a root component, adjust the effectivity dates by
10174 --intersecting with parent's actual effectivity dates, which have already been
10175 --calculated because of the hierarchichal order of the query.
10176 --Actual effective date interval is the intersection of parent's actual effective
10177 --date interval with child's nominal effective date interval. Again, no nulls.
10178
10179 IF(ntParentId(i) IS NOT NULL)THEN
10180
10181 localCount := glIndexByPsNodeId(ntParentId(i));
10182 IF(glEffFrom(localCount) > CurrentEffFrom)THEN CurrentEffFrom := glEffFrom(localCount); END IF;
10183 IF(glEffUntil(localCount) < CurrentEffUntil)THEN CurrentEffUntil := glEffUntil(localcount); END IF;
10184
10185 --Adjust usage mask here. CurrentUsageMask is now OR-ed with glUsageMask(localCount)
10186 CurrentUsageMask := RAWTOHEX(UTL_RAW.BIT_OR(HEXTORAW(LPAD(CurrentUsageMask,16,'0')),HEXTORAW(glUsageMask(localCount))));
10187
10188 END IF;
10189
10190 --From now on the local variables (dtEff) or effectivity set, if defined, will contain
10191 --the nominal effective date interval while the global variables (glEff) will contain
10192 --the actual (intersected with parent) effective date interval.
10193 --The same is true for the usage mask nominal/actual values.
10194
10195 glEffFrom(globalCount) := CurrentEffFrom;
10196 glEffUntil(globalCount) := CurrentEffUntil;
10197 glUsageMask(globalCount) := CurrentUsageMask;
10198
10199 glHeaderByPsNodeId(ntPsNodeId(i)) := nStructureHeaderId;
10200 globalCount := globalCount + 1;
10201
10202 ELSE
10203
10204 localCount := glIndexByPsNodeId(ntPsNodeId(i));
10205 CurrentEffFrom := glEffFrom(localCount);
10206 CurrentEffUntil := glEffUntil(localCount);
10207 CurrentUsageMask := glUsageMask(localCount);
10208
10209 END IF;
10210
10211 nDebug := 1110012;
10212
10213 IF(isLogicGenerated.EXISTS(inComponentId))THEN
10214
10215 --We need to call the procedure for any non-virtual component (bug #2065239) and for any
10216 --component and reference.
10217
10218 IF(ntPsNodeType(i) IN (PS_NODE_TYPE_REFERENCE, PS_NODE_TYPE_CONNECTOR))THEN
10219
10220 --Check for circularity.
10221
10222 localCount := 0;
10223
10224 FOR n IN 1..globalLevel LOOP
10225 IF(globalStack(n) = ntReferenceId(i))THEN
10226
10227 --Circularity detected.
10228
10229 localCount := 1;
10230 EXIT;
10231 END IF;
10232 END LOOP;
10233
10234 IF(localCount = 0)THEN
10235
10236 globalLevel := globalLevel + 1;
10237 globalStack(globalLevel) := ntReferenceId(i);
10238 globalRef(globalLevel) := ntPsNodeId(i);
10239
10240 IF(ntPsNodeType(i) = PS_NODE_TYPE_REFERENCE)THEN
10241
10242 localMinString := TO_CHAR(ntMinimum(i));
10243 IF(localMinString IS NULL)THEN localMinString := '0'; END IF;
10244 localMaxString := TO_CHAR(ntMaximum(i));
10245 IF(localMaxString IS NULL)THEN localMaxString := '-1'; END IF;
10246
10247 --Store the information on the instantiability of the reference on the stack.
10248
10249 IF(localMinString = '1' AND localMaxString = '1')THEN
10250 globalInstance(globalLevel) := 0;
10251 ELSE
10252 globalInstance(globalLevel) := 1;
10253 END IF;
10254 ELSE
10255 --This is a connector and instantiability is not defined, but we need a value on
10256 --the stack.
10257
10258 globalInstance(globalLevel) := 0;
10259 END IF;
10260
10261 GENERATE_COMPONENT_TREE(ntReferenceId(i), ntReferenceId(i), NULL);
10262 globalLevel := globalLevel - 1;
10263
10264 --Bug #5003285. Need to move the propagation of trackable flag into this branch which
10265 --executes even if child model is up-to-date.
10266
10267 IF(ntPsNodeType(i) = PS_NODE_TYPE_REFERENCE AND rootProjectType = MODEL_TYPE_CONTAINER_MODEL AND
10268
10269 --All the following verifications are to be made only if the referenced model is
10270 --a BOM Model - bug #2509208.
10271
10272 glPsNodeType(glIndexByPsNodeId(ntReferenceId(i))) IN
10273 (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
10274
10275 --If the referenced model is trackable it may be a trackable leaf. However, if its
10276 --trackableAncestor flag exists, it has trackable children. In any case we need to
10277 --mark all of its ancestors and make sure their quantities are not greater than 1,
10278 --because the root is a container model here.
10279
10280 IF(glIbTrackable(ntReferenceId(i)) = FLAG_IB_TRACKABLE OR
10281 trackableAncestor.EXISTS(ntReferenceId(i)))THEN
10282
10283 trackableAncestor(ntPsNodeId(i)) := 1;
10284 PROPAGATE_TRACKABLE_ANCESTOR;
10285 END IF;
10286 END IF;
10287 END IF;
10288
10289 ELSIF(ntVirtualFlag(i) = FLAG_NON_VIRTUAL AND
10290 ntPsNodeType(i) IN (PS_NODE_TYPE_COMPONENT, PS_NODE_TYPE_PRODUCT) AND
10291 ntPsNodeId(i) <> inComponentId)THEN
10292
10293 --We emulate the component as a model with generated logic because we do not want to
10294 --generate anything but still want to follow everything underneath this component.
10295
10296 IsLogicGenerated(ntPsNodeId(i)) := 1;
10297
10298 --We can pass logic header as NULL because it will never be actually used.
10299
10300 GENERATE_COMPONENT_TREE(ntPsNodeId(i), inProjectId, 0);
10301 END IF;
10302
10303 --Bug #5003285. Need to move the propagation of trackable flag into this branch which
10304 --executes even if child model is up-to-date.
10305
10306 IF(rootProjectType = MODEL_TYPE_CONTAINER_MODEL AND
10307 ntPsNodeType(i) IN (PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD) AND
10308 glIbTrackable(ntPsNodeId(i)) = FLAG_IB_TRACKABLE)THEN
10309
10310 PROPAGATE_TRACKABLE_ANCESTOR;
10311
10312 --If the item is tangible, we should prohibit not only its ancestors but also itself
10313 --from being on the RHS of numeric rules - TSO with Equipment.
10314
10315 IF(ntShippableFlag(i) = '1')THEN trackableAncestor(ntPsNodeId(i)) := 2; END IF;
10316 END IF;
10317
10318 --If no logic already exists, generate the structure.
10319
10320 ELSE
10321
10322 GENERATE_EFFECTIVITY_LOGIC(CurrentEffFrom, CurrentEffUntil, CurrentUsageMask);
10323
10324 IF(ntPsNodeType(i) = PS_NODE_TYPE_OPTION)THEN
10325
10326 --We are in a feature's options. The important assumption here is that a feature
10327 --can have only options as it's children,so feature's children list is dense and
10328 --all the feature's children should be processed, and this list starts here.
10329 --In other words, we assume that as soon as we encountered the first option of a
10330 --feature, we will be dealing only with options of this feature until we process
10331 --all of them.
10332
10333 /*--The restriction is removed (bug #1746927)-----------------------------------
10334 --First make sure that there aren't too many options.
10335 IF(optionCounter > MAX_NUMBER_OF_OPTIONS)THEN
10336 --This will be fatal and terminate the logic generation
10337 --'Option feature has more than maximum allowed number of options, feature ''%FEATNAME'''
10338 errorMessage := CZ_UTILS.GET_TEXT('CZ_S_TOO_MANY_OPTIONS', 'FEATNAME', ntName(i));
10339 RAISE CZ_S_TOO_MANY_OPTIONS;
10340 END IF;
10341 ------------------------------------------------------------------------------*/
10342
10343 optionCounter := optionCounter + 1;
10344
10345 --Generate the option: OBJECT P_<OptID> R
10346 vLogicLine := 'OBJECT P_' || TO_CHAR(ntPersistentId(i)) || ' R' || NewLine;
10347
10348 --If this is the last option, we will generate the feature right here
10349
10350 IF(ntParentId(i + 1) <> ntParentId(i))THEN
10351
10352 --Done with options, ready to generate the feature, put in the stored
10353 --effectivity information.
10354
10355 PACK;
10356 GENERATE_EFFECTIVITY_LOGIC(FeatureEffFrom, FeatureEffUntil, FeatureUsageMask);
10357
10358 --This is the feature index
10359
10360 j := i - optionCounter;
10361
10362 --Generate the feature itself. Local variables here are inherited from the feature
10363 --generation section.
10364 --But before that adjust the minimum number of selected children to the actual number
10365 --of options - bug #2233795.
10366
10367 IF(ntMinimum(j) IS NOT NULL AND ntMinimum(j) > optionCounter)THEN
10368
10369 localMinString := TO_CHAR(optionCounter);
10370 END IF;
10371
10372 vLogicLine := 'SGN P_' || TO_CHAR(ntPersistentId(j)) || ' R ' || localMinString || ' ' ||
10373 localMaxString || ' _';
10374
10375 nDebug := 1110028;
10376
10377 --Generate the list of options for the feature
10378
10379 WHILE(j < i)LOOP
10380
10381 j := j + 1;
10382
10383 --This call is necessary here for wrapping
10384
10385 PACK;
10386 vLogicLine := ' P_' || TO_CHAR(ntPersistentId(j));
10387
10388 nDebug := 1110029;
10389
10390 END LOOP;
10391
10392 --We must put [new line] after the list of options
10393
10394 vLogicLine := vLogicLine || NewLine;
10395 j := i - optionCounter;
10396
10397 PACK;
10398 GENERATE_ACCUMULATOR(j);
10399 generatingFeature := 0;
10400
10401 --Minimum number of selected options greater than the actual number of options.
10402 --The feature is already generated and now will be reported.
10403
10404 IF(ntMinimum(j) IS NOT NULL AND ntMinimum(j) > optionCounter)THEN
10405
10406 RAISE CZ_S_ILLEGAL_OPTION_FEATURE;
10407 END IF;
10408
10409 END IF;
10410
10411 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_TOTAL OR
10412 ntPsNodeType(i) = PS_NODE_TYPE_RESOURCE)THEN
10413
10414 nDebug := 1110014;
10415
10416 --This is a total or resource: TOTAL P_<Tot/ResID> R [tot/res initial value]
10417
10418 vLogicLine := 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || ' R ' ||
10419 ntInitialValue(i) || NewLine;
10420 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_FEATURE)THEN
10421
10422 nDebug := 1110015;
10423
10424 --This is a feature, so consider different subtypes
10425
10426 IF(ntFeatureType(i) IS NULL OR ntFeatureType(i) = PS_NODE_FEATURE_TYPE_INTEGER)THEN
10427
10428 nDebug := 1110016;
10429
10430 --This is an integer feature: real integer or count
10431
10432 IF(ntMinimum(i) IS NULL OR ntMinimum(i) < 0)THEN
10433
10434 nDebug := 1110017;
10435
10436 --This is a real integer feature: TOTAL P_<FeatID> R [initial_value]
10437
10438 vLogicLine := 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || ' R ' ||
10439 ntInitialValue(i) || NewLine;
10440 ELSE
10441
10442 nDebug := 1110018;
10443
10444 --This is a count feature: OBJECT P_<FeatID> R [initial_value]
10445
10446 /* This is rolled back as a fix for the bug #1994924.
10447
10448 --If initial value is not specified and minimum value is greater than 0, we
10449 --define the initial value to be equal to the minimum value. Bug #1834581.
10450
10451 IF(ntInitialValue(i) IS NULL)THEN
10452 ntInitialValue(i) := ntMinimum(i);
10453 END IF;
10454 */
10455 vLogicLine := 'OBJECT P_' || TO_CHAR(ntPersistentId(i)) || ' R ' ||
10456 ntInitialValue(i) || NewLine;
10457 END IF;
10458 ELSIF(ntFeatureType(i) = PS_NODE_FEATURE_TYPE_FLOAT)THEN
10459
10460 nDebug := 1110019;
10461
10462 --This is a decimal feature: TOTAL P_<FeatID> R [initial_value]
10463
10464 /* This is rolled back as a fix for the bug #1994924.
10465
10466 --If initial value is not specified and minimum value is specified and is greater than 0,
10467 --we define the initial value to be equal to the minimum value. Bug #1834581.
10468
10469 IF(ntInitialValue(i) IS NULL AND ntMinimum(i) > 0)THEN
10470 ntInitialValue(i) := ntMinimum(i);
10471 END IF;
10472 */
10473 vLogicLine := 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || ' R ' ||
10474 ntInitialValue(i) || NewLine;
10475 ELSIF(ntFeatureType(i) = PS_NODE_FEATURE_TYPE_BOOLEAN)THEN
10476
10477 nDebug := 1110020;
10478
10479 --This is a boolean feature
10480
10481 vLogicLine := 'OBJECT P_' || TO_CHAR(ntPersistentId(i)) || ' R' || NewLine;
10482 IF(ntInitialValue(i) IS NOT NULL)THEN
10483 IF(ntInitialValue(i) = '1')THEN
10484
10485 nDebug := 1110021;
10486
10487 --Initial value is 'True', create a default rule from an always true object
10488 --toward this one
10489
10490 vLogicLine := vLogicLine || 'OBJECT D_' || TO_CHAR(ntPersistentId(i)) || '_IV' || NewLine ||
10491 'WITH _default = _ALWAYS_TRUE' || NewLine ||
10492 'GS R ... ' || TO_CHAR(ntDescriptionId(i)) || NewLine ||
10493 'GL N D_' || TO_CHAR(ntPersistentId(i)) || '_IV' || NewLine ||
10494 'GR N P_' || TO_CHAR(ntPersistentId(i)) || NewLine;
10495
10496 -- vLogicLine := vLogicLine || 'WITH _default = _ALWAYS_TRUE' || NewLine;
10497
10498 ELSIF(ntInitialValue(i) = '0')THEN
10499
10500 nDebug := 1110022;
10501
10502 --Initial value is 'False', create a temporary object and an additional
10503 --'negates' relation
10504
10505 vLogicLine := vLogicLine || 'OBJECT D_' || TO_CHAR(ntPersistentId(i)) || '_IV' || NewLine ||
10506 'WITH _default = _ALWAYS_TRUE' || NewLine ||
10507 'GS N ... ' || TO_CHAR(ntDescriptionId(i)) || NewLine ||
10508 'GL N D_' || TO_CHAR(ntPersistentId(i)) || '_IV' || NewLine ||
10509 'GR N P_' || TO_CHAR(ntPersistentId(i)) || NewLine;
10510
10511 ELSE
10512
10513 RAISE CZ_S_BAD_BOOLEAN_FEAT_VALUE;
10514
10515 END IF;
10516 END IF;
10517
10518 ELSIF(ntFeatureType(i) = PS_NODE_FEATURE_TYPE_STRING)THEN
10519
10520 nDebug := 1110023;
10521
10522 NULL;
10523
10524 /* Do not need to generate anything for text features.
10525
10526 --This is a text feature
10527
10528 vLogicLine := 'TEXT P_' || TO_CHAR(ntPersistentId(i)) || ' R "' ||
10529 ntInitialValue(i) || '"' || NewLine;
10530 */
10531 ELSIF(ntFeatureType(i) = PS_NODE_FEATURE_TYPE_OPTION)THEN
10532
10533 --Set the options counter
10534
10535 optionCounter := 0;
10536
10537 --Prepare Min, Max values for later use
10538 --Use intermediate variable instead of using NVL because this is faster
10539 --This values will be used also when generating the last option of the feature
10540
10541 localMinString := TO_CHAR(ntMinimum(i));
10542 IF(localMinString IS NULL)THEN localMinString := '0'; END IF;
10543 localMaxString := TO_CHAR(ntMaximum(i));
10544 IF(localMaxString IS NULL)THEN localMaxString := '-1'; END IF;
10545
10546 --Save feature's effective intervals and usage mask for feature generating type
10547
10548 FeatureEffFrom := CurrentEffFrom;
10549 FeatureEffUntil := CurrentEffUntil;
10550 FeatureUsageMask := CurrentUsageMask;
10551
10552 nDebug := 1110024;
10553
10554 --Check if there are any children, report if not
10555
10556 IF(ntParentId(i + 1) <> ntPsNodeId(i))THEN
10557
10558 --No options, still want to generate the feature even with empty options list
10559
10560 vLogicLine := 'SGN P_' || TO_CHAR(ntPersistentId(i)) || ' R ' || localMinString || ' ' ||
10561 localMaxString || ' _' || NewLine;
10562
10563 --No children, report the feature
10564 RAISE CZ_S_FEATURE_NO_CHILDREN;
10565 END IF;
10566
10567 --Now proceed with the cycle. As options of the feature directly follows it in memory,
10568 --we will be generating them right away. After the last option, the feature itself will
10569 --be generated (see options generating code).
10570
10571 generatingFeature := 1;
10572
10573 nDebug := 1110027;
10574
10575 ELSE
10576
10577 --'Unknown feature type, feature ''%FEATNAME'''
10578 errorMessage := CZ_UTILS.GET_TEXT('CZ_S_UNKNOWN_FEATURE_TYPE', 'FEATNAME', ntName(i));
10579 RAISE CZ_S_UNKNOWN_FEATURE_TYPE;
10580 END IF;
10581 ELSIF(ntPsNodeType(i) IN (PS_NODE_TYPE_COMPONENT, PS_NODE_TYPE_PRODUCT) AND
10582 ntVirtualFlag(i) = FLAG_NON_VIRTUAL)THEN
10583
10584 nDebug := 1110030;
10585
10586 --We don't want to go into an infinite cycle - don't call the procedure for the current
10587 --root component
10588
10589 IF(ntPsNodeId(i) <> inComponentId)THEN
10590
10591 --This is another non-virtual component. Call this function for it - recursion
10592 --Use intermediate variable instead of using NVL because this is faster
10593
10594 localMinString := TO_CHAR(ntMinimum(i));
10595 IF(localMinString IS NULL)THEN localMinString := '0'; END IF;
10596 localMaxString := TO_CHAR(ntMaximum(i));
10597 IF(localMaxString IS NULL)THEN localMaxString := '-1'; END IF;
10598
10599 vLogicLine := 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || '_MIN R ' || localMinString || NewLine ||
10600 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || '_MAX R ' || localMaxString || NewLine ||
10601 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || '_ACTUALCOUNT R 0' || NewLine;
10602
10603 GENERATE_COMPONENT_TREE(ntPsNodeId(i), inProjectId, nStructureHeaderId);
10604 END IF;
10605
10606 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_REFERENCE)THEN
10607
10608 nDebug := 1110031;
10609
10610 --Check for circularity.
10611
10612 localCount := 0;
10613 trackableContext := 0;
10614 instantiableContext := 0;
10615
10616 FOR n IN 1..globalLevel LOOP
10617
10618 IF(globalStack(n) = ntReferenceId(i))THEN
10619
10620 --Circularity detected.
10621
10622 localCount := 1;
10623 EXIT;
10624 END IF;
10625
10626 IF(glIbTrackable(globalStack(n)) = FLAG_IB_TRACKABLE)THEN
10627
10628 trackableContext := globalStack(n);
10629 END IF;
10630
10631 IF(globalInstance(n) = 1)THEN
10632
10633 instantiableContext := globalStack(n);
10634 END IF;
10635 END LOOP;
10636
10637 localMinString := TO_CHAR(ntMinimum(i));
10638 IF(localMinString IS NULL)THEN localMinString := '0'; END IF;
10639 localMaxString := TO_CHAR(ntMaximum(i));
10640 IF(localMaxString IS NULL)THEN localMaxString := '-1'; END IF;
10641
10642 IF(ntVirtualFlag(i) = FLAG_NON_VIRTUAL)THEN
10643
10644 vLogicLine := 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || '_MIN R ' || localMinString || NewLine ||
10645 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || '_MAX R ' || localMaxString || NewLine ||
10646 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || '_ACTUALCOUNT R 0' || NewLine;
10647 END IF;
10648
10649 IF(localCount = 0)THEN
10650
10651 --Follow the reference, doesn't affect the current LCE file.
10652 --Use intermediate variable instead of using NVL because this is faster.
10653 --Maintain the stack of references - needed to be able to detect dead-loops.
10654
10655 globalLevel := globalLevel + 1;
10656 globalStack(globalLevel) := ntReferenceId(i);
10657 globalRef(globalLevel) := ntPsNodeId(i);
10658
10659 --Store the information on the instantiability of the reference on the stack.
10660
10661 IF(localMinString = '1' AND localMaxString = '1')THEN
10662 globalInstance(globalLevel) := 0;
10663 ELSE
10664 globalInstance(globalLevel) := 1;
10665 END IF;
10666
10667 GENERATE_COMPONENT_TREE(ntReferenceId(i), ntReferenceId(i), NULL);
10668 globalLevel := globalLevel - 1;
10669
10670 IF(rootProjectType = MODEL_TYPE_CONTAINER_MODEL AND
10671
10672 --All the following verifications are to be made only if the referenced model is
10673 --a BOM Model - bug #2509208.
10674
10675 glPsNodeType(glIndexByPsNodeId(ntReferenceId(i))) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
10676
10677 errorMessage := glName(glIndexByPsNodeId(ntReferenceId(i)));
10678
10679 --If this is a network container model, every reference to a trackable model should
10680 --have exactly minimum = 0 and maximum = -1. This validation must be made after the
10681 --referenced model is processed so that its IB_TRACKABLE flag has become available.
10682 --IB_TRACKABLE flag for the instantiably referenced model should not be null.
10683
10684 IF(glIbTrackable(ntReferenceId(i)) IS NULL)THEN
10685
10686 RAISE CZ_S_NO_TRACKABLE_FLAG;
10687
10688 ELSIF(trackableContext = 0 AND glIbTrackable(ntReferenceId(i)) = FLAG_IB_TRACKABLE)THEN
10689
10690 --This is a trackable instance model, make additional verifications.
10691
10692 IF(instanceModel.EXISTS(ntReferenceId(i)) AND
10693 (globalLevel > 1 OR instanceModel(ntReferenceId(i)) > 1))THEN
10694
10695 --Multiple occurrences of a trackable instance model. We allow them only if all
10696 --of them are immediate children of the container model, because they may have
10697 --different effectivity ranges.
10698
10699 nParam := glIndexByPsNodeId(globalStack(globalLevel - 1));
10700 RAISE CZ_S_MULTIPLE_TRACKABLE;
10701
10702 ELSIF(instantiableContext > 0)THEN
10703
10704 --One of the ancestors of the trackable instance model is multiply instantiable.
10705
10706 nParam := glIndexByPsNodeId(instantiableContext);
10707 RAISE CZ_S_MULTIPLE_INSTANCES;
10708
10709 ELSIF(localMinString <> '0' OR localMaxString <> '-1')THEN
10710
10711 --Incorrect instance numbers for a reference to a trackable instance model.
10712
10713 RAISE CZ_S_INCORRECT_CONTAINER;
10714
10715 ELSE
10716
10717 instanceModel(ntReferenceId(i)) := globalLevel;
10718 END IF;
10719 END IF;
10720
10721 --If the referenced model is trackable it may be a trackable leaf. However, if its
10722 --trackableAncestor flag exists, it has trackable children. In any case we need to
10723 --mark all of its ancestors and make sure their quantities are not greater than 1,
10724 --because the root is a container model here.
10725
10726 IF(glIbTrackable(ntReferenceId(i)) = FLAG_IB_TRACKABLE OR
10727 trackableAncestor.EXISTS(ntReferenceId(i)))THEN
10728
10729 trackableAncestor(ntPsNodeId(i)) := 1;
10730 PROPAGATE_TRACKABLE_ANCESTOR;
10731 END IF;
10732 END IF;
10733 END IF;
10734
10735 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_CONNECTOR)THEN
10736
10737 --Go and generate the connection target. At least we need to have its structure in
10738 --memory, but there is also a versioning problem.
10739 --Check for circularity.
10740
10741 localCount := 0;
10742 trackableContext := 0;
10743
10744 FOR n IN 1..globalLevel LOOP
10745 IF(globalStack(n) = ntReferenceId(i))THEN
10746
10747 --Circularity detected.
10748
10749 localCount := 1;
10750 EXIT;
10751 END IF;
10752
10753 IF(glIbTrackable(globalStack(n)) = FLAG_IB_TRACKABLE)THEN
10754
10755 trackableContext := globalStack(n);
10756 END IF;
10757 END LOOP;
10758
10759 IF(localCount = 0)THEN
10760
10761 globalLevel := globalLevel + 1;
10762 globalStack(globalLevel) := ntReferenceId(i);
10763 globalRef(globalLevel) := ntPsNodeId(i);
10764
10765 --This is a connector and instantiability is not defined, but we need a value on
10766 --the stack.
10767
10768 globalInstance(globalLevel) := 0;
10769
10770 GENERATE_COMPONENT_TREE(ntReferenceId(i), ntReferenceId(i), NULL);
10771 globalLevel := globalLevel - 1;
10772
10773 IF(rootProjectType = MODEL_TYPE_CONTAINER_MODEL)THEN
10774
10775 --Definition: trackable instance model is a trackable model that has no trackable
10776 --ancestors. In a container model no connectors to trackable instance models are
10777 --allowed. In other words, any connector to a trackable model in a container model
10778 --should be inside a trackable child of the container model.
10779
10780 IF(glIbTrackable(ntReferenceId(i)) = FLAG_IB_TRACKABLE AND trackableContext = 0)THEN
10781
10782 errorMessage := thisProjectName;
10783 nParam := glIndexByPsNodeId(ntReferenceId(i));
10784 RAISE CZ_S_CONNECTOR_TRACKABLE;
10785 END IF;
10786
10787 --Inside a trackable model no connector to a non-trackable model is allowed on any
10788 --level in a container model.
10789
10790 IF((glIbTrackable(ntReferenceId(i)) IS NULL OR glIbTrackable(ntReferenceId(i)) <> FLAG_IB_TRACKABLE) AND
10791 trackableContext > 0)THEN
10792
10793 errorMessage := glName(glIndexByPsNodeId(ntReferenceId(i)));
10794 nParam := glIndexByPsNodeId(trackableContext);
10795 RAISE CZ_S_CONNECT_NONTRACKABLE;
10796 END IF;
10797 END IF;
10798 END IF;
10799
10800 ELSIF(ntPsNodeType(i) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
10801
10802 nDebug := 1110032;
10803
10804 --Run the TSO with Equipment validations before generating logic.
10805
10806 IF(rootProjectType = MODEL_TYPE_CONTAINER_MODEL OR
10807 thisProjectType = MODEL_TYPE_CONTAINER_MODEL)THEN
10808
10809 errorMessage := thisProjectName;
10810 thisName := ntName(i);
10811 parentName := '';
10812 IF(ntParentId(i) IS NOT NULL)THEN parentName := glName(glIndexByPsNodeId(ntParentId(i))); END IF;
10813
10814 IF(ntShippableFlag(i) IS NULL OR ntTransactableFlag(i) IS NULL OR
10815 ntAtoFlag(i) IS NULL OR ntSerializableFlag(i) IS NULL) THEN
10816
10817 --'The BOM Model ''%MODELNAME'' is out of date. Please refresh the Model by running the Refresh a Single
10818 -- Configuration Model concurrent program and then regenerate the Active Model.'
10819
10820 RAISE CZ_LCE_MODEL_OUTOFDATE;
10821 END IF; --The new flags are null, need to refresh.
10822
10823 IF((ntPsNodeType(i) IN (PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_MODEL)) AND
10824 (ntShippableFlag(i) = '1' OR ntTransactableFlag(i) = '1'))THEN
10825
10826 --'Incorrect BOM Model or Option Class ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
10827 -- Only BOM Standard Items can be shippable and inventory transactable.'
10828
10829 RAISE CZ_LCE_INCORRECT_BOM;
10830 END IF; --Flags are set for a non-Standard item node.
10831
10832 IF(ntPsNodeType(i) = PS_NODE_TYPE_BOM_STANDARD)THEN
10833 IF(ntShippableFlag(i) <> ntTransactableFlag(i))THEN
10834
10835 --'Incorrect BOM Standard Item ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
10836 -- All shippable items should be inventory transactable and vice versa.'
10837
10838 RAISE CZ_LCE_INCORRECT_ITEM;
10839 END IF; -- ntShippableFlag <> ntTransactableFlag.
10840
10841 IF(ntShippableFlag(i) = '1' AND ((ntAtoFlag(i) <> '0') OR (NVL(ntIbTrackable(i), '0') <> '1')))THEN
10842
10843 --'Incorrect BOM Standard Item ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
10844 -- All shippable items should be trackable non-ATO standard items with maximum quantity 1.'
10845
10846 RAISE CZ_LCE_INCORRECT_TANGIBLE;
10847 END IF; --ntShippableFlag = '1'.
10848
10849 IF(ntShippableFlag(i) = '1' AND ntSerializableFlag(i) = '0')THEN
10850
10851 --'Incorrect BOM Standard Item ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
10852 -- All shippable items should be serializable trackable non-ATO standard items.'
10853
10854 RAISE CZ_LCE_INCORRECT_SHIPPABLE;
10855 END IF; --ntShippableFlag = '1' AND ntSerializableFlag = '0';
10856 END IF; --Standard Item.
10857 END IF; --MACD Container.
10858
10859 nDebug := 1110033;
10860
10861 --Generate header.
10862
10863 vLogicLine := 'BOM P_' || TO_CHAR(ntPersistentId(i)) || ' R ';
10864
10865 --BOM modifier.
10866
10867 IF(ntPsNodeType(i) = PS_NODE_TYPE_BOM_STANDARD)THEN
10868 vLogicLine := vLogicLine || 'S';
10869 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_BOM_OPTIONCLASS)THEN
10870 vLogicLine := vLogicLine || 'O';
10871 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_BOM_MODEL)THEN
10872 vLogicLine := vLogicLine || 'M';
10873
10874 --This is a BOM model, it can be only the root model, so that thisProjectType and
10875 --thisProjectName are currently referring to it.
10876
10877 IF(ntIbTrackable(i) = FLAG_IB_TRACKABLE AND thisProjectType = MODEL_TYPE_CONTAINER_MODEL)THEN
10878
10879 --A network container model should not be trackable.
10880
10881 errorMessage := thisProjectName;
10882 RAISE CZ_S_TRACKABLE_CONTAINER;
10883 END IF;
10884 ELSE
10885
10886 --'Unknown BOM node type, node ''%NODENAME'''
10887 errorMessage := CZ_UTILS.GET_TEXT('CZ_S_UNKNOWN_BOM_NODE_TYPE', 'NODENAME', ntName(i));
10888 RAISE CZ_S_UNKNOWN_BOM_NODE_TYPE;
10889 END IF;
10890
10891 IF(ntPsNodeType(i) IN (PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD) AND
10892 glIbTrackable(ntPsNodeId(i)) = FLAG_IB_TRACKABLE)THEN
10893
10894 --Trackable Standard Items/Option Classes are not allowed as immediate children of a
10895 --network container model.
10896
10897 IF(thisProjectType = MODEL_TYPE_CONTAINER_MODEL AND
10898 glPsNodeType(glIndexByPsNodeId(ntParentId(i))) = PS_NODE_TYPE_BOM_MODEL)THEN
10899
10900 errorMessage := thisProjectName;
10901 nParam := glIndexByPsNodeId(ntPsNodeId(i));
10902 RAISE CZ_S_TRACKABLE_CHILDREN;
10903 END IF;
10904
10905 --As this is a trackable Standard Item or Option Class we need to mark all of its
10906 --ancestors and make sure their quantities are not greater than 1, if the root is
10907 --a container model.
10908
10909 IF(rootProjectType = MODEL_TYPE_CONTAINER_MODEL)THEN
10910
10911 PROPAGATE_TRACKABLE_ANCESTOR;
10912
10913 --If the item is tangible, we should prohibit not only its ancestors but also itself
10914 --from being on the RHS of numeric rules - TSO with Equipment.
10915
10916 IF(ntShippableFlag(i) = '1')THEN trackableAncestor(ntPsNodeId(i)) := 2; END IF;
10917 END IF;
10918 END IF;
10919
10920 --Add the decimal quantity modifier if necessary
10921
10922 IF(ntDecimalQty(i) = FLAG_DECIMAL_QTY)THEN
10923 vLogicLine := vLogicLine || 'D';
10924 END IF;
10925
10926 nDebug := 1110034;
10927
10928 --BOM required flag + minimum which is always 0
10929
10930 IF(ntBomRequired(i) = FLAG_BOM_REQUIRED)THEN
10931 vLogicLine := vLogicLine || ' RC 0 ';
10932 ELSE
10933 vLogicLine := vLogicLine || ' NRC 0 ';
10934 END IF;
10935
10936 nDebug := 1110035;
10937
10938 --Maximum selected
10939
10940 IF(ntMaximumSel(i) IS NOT NULL)THEN
10941 vLogicLine := vLogicLine || TO_CHAR(ntMaximumSel(i)) || ' ';
10942 ELSE
10943 vLogicLine := vLogicLine || '-1 ';
10944 END IF;
10945
10946 nDebug := 1110036;
10947
10948 --Parent 'logic' name if any
10949
10950 IF(ntParentId(i) IS NOT NULL AND
10951 glPsNodeType(glIndexByPsNodeId(ntParentId(i))) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
10952
10953 --Fix for the bug #1745394. If a BOM parent is of decimal quantity and it's child is of
10954 --integer quantity, fatal error will be raised.
10955
10956 IF(glDecimalQty(ntParentId(i)) = FLAG_DECIMAL_QTY AND ntDecimalQty(i) = FLAG_INTEGER_QTY)THEN
10957
10958 --'Node ''%CHILDNAME'' must allow decimal quantity since its parent ''%PARENTNAME'' allows decimal quantity'
10959 errorMessage := CZ_UTILS.GET_TEXT('CZ_S_INCONSISTENT_QUANTITY', 'CHILDNAME', ntName(i),
10960 'PARENTNAME', glName(glIndexByPsNodeId(ntParentId(i))));
10961 RAISE CZ_S_INCONSISTENT_QUANTITY;
10962 END IF;
10963
10964 vLogicLine := vLogicLine || 'P_' || TO_CHAR(glPersistentId(ntParentId(i))) || ' ';
10965 END IF;
10966
10967 nDebug := 1110037;
10968
10969 --Default quantity. If initial_value is not null and can't be converted to
10970 --a number the VALUE_ERROR exception will be raised. We catch this one and
10971 --re-raise our own exception for better reporting.
10972
10973 BEGIN
10974 IF(ntInitialValue(i) IS NOT NULL AND TO_NUMBER(ntInitialValue(i)) > 0)THEN
10975 vLogicLine := vLogicLine || ntInitialValue(i) || ' ... ' || ntDescriptionId(i) || NewLine;
10976 ELSE
10977 vLogicLine := vLogicLine || '0' || ' ... ' || ntDescriptionId(i) || NewLine;
10978 END IF;
10979 EXCEPTION
10980 WHEN VALUE_ERROR THEN
10981 RAISE CZ_S_WRONG_INITIAL_VALUE;
10982 END;
10983
10984 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_FEATUREGROUP)THEN
10985
10986 NULL;
10987
10988 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_COMPONENT)THEN
10989
10990 NULL;
10991
10992 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_PRODUCT)THEN
10993
10994 NULL;
10995
10996 ELSE
10997
10998 --'Unknown node type, node ''%NODENAME'''
10999 errorMessage := CZ_UTILS.GET_TEXT('CZ_S_UNKNOWN_NODE_TYPE', 'NODENAME', ntName(i));
11000 RAISE CZ_S_UNKNOWN_NODE_TYPE;
11001 END IF;
11002 END IF; --End of the IF block of 'if logic does not already exist' inside the main loop
11003
11004 --This exception handler may be used to catch the 'logic item'-level exceptions
11005 --that shouldn't stop the process. If an exception is re-raised here it becomes
11006 --a fatal exception (warning vs. errors).
11007
11008 EXCEPTION
11009 WHEN CZ_S_BAD_BOOLEAN_FEAT_VALUE THEN
11010 --'Bad boolean feature value, feature ''%FEATNAME'''
11011 REPORT(CZ_UTILS.GET_TEXT('CZ_S_BAD_BOOLEAN_FEAT_VALUE', 'FEATNAME', ntName(i)), 1);
11012 WHEN CZ_S_FEATURE_NO_CHILDREN THEN
11013 --'Option feature has no children, feature ''%FEATNAME'''
11014 REPORT(CZ_UTILS.GET_TEXT('CZ_S_FEATURE_NO_CHILDREN', 'FEATNAME', ntName(i)), 1);
11015 WHEN CZ_S_ILLEGAL_OPTION_FEATURE THEN
11016 --'Feature ''%FEATNAME'' has no options or fewer options than its minimum count, feature ''%FEATNAME'''
11017 REPORT(CZ_UTILS.GET_TEXT('CZ_S_ILLEGAL_OPTION_FEATURE', 'FEATNAME', ntName(j)), 1);
11018 WHEN CZ_S_WRONG_INITIAL_VALUE THEN
11019 --'Initial value of BOM node is not null and can not be converted to number, node ''%NODENAME'''
11020 REPORT(CZ_UTILS.GET_TEXT('CZ_S_WRONG_INITIAL_VALUE', 'NODENAME', ntName(i)), 1);
11021
11022 --Fatal exceptions section. Exceptions are re-raised to be reported at the higher level.
11023
11024 WHEN CZ_S_DEADLOOP_DETECTED THEN --Currently never thrown.
11025 --As per bug #3593513, when thrown should probably be moved to the place where thrown. Otherwise going up from
11026 --the recursion overwites the message substituting incorrect names.
11027
11028 --'An infinite loop detected: models ''%MODELNAME'' and ''%CHILDNAME'' reference each other'
11029 errorMessage := CZ_UTILS.GET_TEXT('CZ_S_DEADLOOP_DETECTED', 'MODELNAME', glName(glIndexByPsNodeId(globalStack(globalLevel))),
11030 'CHILDNAME', glName(glIndexByPsNodeId(globalStack(nParam))));
11031 RAISE;
11032 END;
11033
11034 --This procedure implements wrapping. A call to it is included in options list generation
11035 --for an option feature above
11036
11037 PACK;
11038
11039 nDebug := 1110040;
11040
11041 IF(NOT IsLogicGenerated.EXISTS(inComponentId))THEN
11042
11043 --generatingFeature is set to 1 when we step over an option feature with actual options. It will
11044 --be unset when we finally generate the feature after all of its options. But while generating
11045 --the options we want to call this procedure for every of them. This is why we check the type
11046 --and if it is an option, call the procedure even though the flag is set.
11047
11048 IF(generatingFeature = 0 OR ntPsNodeType(i) = PS_NODE_TYPE_OPTION)THEN GENERATE_ACCUMULATOR(i); END IF;
11049 END IF;
11050
11051 --Increase the main cycle counter
11052
11053 i := i + 1;
11054
11055 END LOOP; --End of the main structure generation cycle
11056
11057 nDebug := 1110038;
11058
11059 ELSE --IF 'there is some data returned'
11060
11061 --The project is empty, stop here.
11062
11063 errorMessage := thisProjectName;
11064 RAISE CZ_S_NO_DATA_IN_PROJECT;
11065
11066 END IF; --Ends the ELSE block of IF 'there is some data returned'
11067
11068 IF(NOT IsLogicGenerated.EXISTS(inComponentId))THEN
11069
11070 --Flush the buffer
11071
11072 IF(vLogicText IS NOT NULL)THEN
11073 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
11074 (nStructureHeaderId, nSequenceNbr, vLogicText);
11075 vLogicText := NULL;
11076 END IF;
11077
11078 --Remember the next sequence number for this logic file. Will be used in
11079 --numeric rules generation for accumulators.
11080
11081 vSeqNbrByHeader(nStructureHeaderId) := nSequenceNbr + 1;
11082
11083 IF(TwoPhaseCommit = 0)THEN COMMIT; END IF;
11084 END IF;
11085
11086 nDebug := 1110039;
11087
11088 --If a model, generate rules and set the logic generated flag.
11089
11090 IF(inParentLogicHeaderId IS NULL)THEN
11091
11092
11093 -- LA 13733007 : No children OC
11094 -- Report option classes with no children or all ineffective children
11095 -- This code is also used in FCE logic gen and BOM Import.
11096 -- Currently repeated this code in all the packages but later need to move to some common place
11097 -- This query is used to report all the OCs under Root model and it's reference chain
11098
11099 IF(inComponentId = inDevlProjectId)THEN
11100 BEGIN
11101 SELECT MODEL.NAME, PARENT.NAME
11102 BULK COLLECT INTO lNoChildOCModelName, lNoChildOCName
11103 FROM cz_ps_nodes PARENT, cz_rp_entries MODEL
11104 WHERE PARENT.deleted_flag = '0'
11105 AND MODEL.deleted_flag = '0'
11106 AND PARENT.devl_project_id = MODEL.object_id
11107 AND MODEL.object_type = 'PRJ'
11108 AND parent.devl_project_id IN
11109 (SELECT DISTINCT component_id FROM cz_model_ref_expls
11110 WHERE deleted_flag = '0' AND model_id = inDevlProjectId
11111 AND (ps_node_type = CZ_TYPES.PS_NODE_TYPE_REFERENCE
11112 OR ps_node_type = CZ_TYPES.PS_NODE_TYPE_BOM_MODEL))
11113 AND PARENT.ps_node_type = CZ_TYPES.PS_NODE_TYPE_BOM_OPTION_CLASS
11114 AND PARENT.effective_until > SYSDATE
11115 AND NOT EXISTS
11116 (SELECT 1 FROM cz_ps_nodes CHILD
11117 WHERE CHILD.deleted_flag = '0'
11118 AND CHILD.devl_project_id = PARENT.devl_project_id
11119 AND CHILD.parent_id = PARENT.ps_node_id
11120 AND CHILD.effective_until > SYSDATE);
11121
11122 IF (lNoChildOCModelName.COUNT > 0) THEN
11123 FOR i IN 1..lNoChildOCModelName.COUNT
11124 LOOP
11125 REPORT('Option class has no effective children, option class ''' || lNoChildOCName(i) || '''', 1);
11126 END LOOP;
11127 END IF;
11128 EXCEPTION
11129 WHEN NO_DATA_FOUND THEN
11130 null;
11131 END;
11132 END IF;
11133 nDebug := 1110041;
11134
11135 --Generate model's rules and expressions if necessary
11136
11137 IF(NOT IsLogicGenerated.EXISTS(inComponentId))THEN
11138 GENERATE_RULES;
11139 IsLogicGenerated(inComponentId) := 1;
11140 END IF;
11141 END IF;
11142 END; --GENERATE_COMPONENT_TREE
11143 ---------------------------------------------------------------------------------------
11144 PROCEDURE COMMIT_HEADERS IS
11145 localOldHeaders tIntegerArray;
11146 nCount PLS_INTEGER := 1;
11147 localComponent NUMBER := NULL; --kdande; Bug 6881902; 11-Mar-2008
11148 BEGIN
11149
11150 FOR i IN 1..NewHeaders.COUNT LOOP
11151 IF(((NOT IsLogicGenerated.EXISTS(NewHeadersComponents(i))) OR IsLogicGenerated(NewHeadersComponents(i)) = 1) AND
11152 (localComponent IS NULL OR NewHeadersComponents(i) <> localComponent))THEN
11153
11154 localOldHeaders.DELETE;
11155
11156 SELECT lce_header_id BULK COLLECT INTO localOldHeaders FROM cz_lce_headers
11157 WHERE deleted_flag = FLAG_NOT_DELETED
11158 AND devl_project_id = NewHeadersComponents(i);
11159
11160 FOR j IN 1..localOldHeaders.COUNT LOOP
11161 OldHeaders(nCount) := localOldHeaders(j);
11162 nCount := nCount + 1;
11163 END LOOP;
11164
11165 localComponent := NewHeadersComponents(i);
11166 END IF;
11167 END LOOP;
11168
11169 FORALL i IN 1..OldHeaders.COUNT
11170 UPDATE cz_lce_headers SET deleted_flag = FLAG_DELETED
11171 WHERE lce_header_id = OldHeaders(i);
11172
11173 FORALL i IN 1..OldHeaders.COUNT
11174 UPDATE cz_lce_load_specs SET deleted_flag = FLAG_DELETED
11175 WHERE lce_header_id = OldHeaders(i);
11176
11177 FORALL i IN 1..NewHeaders.COUNT
11178 UPDATE cz_lce_headers SET deleted_flag = FLAG_NOT_DELETED
11179 WHERE lce_header_id = NewHeaders(i);
11180
11181 FORALL i IN 1..NewHeaders.COUNT
11182 UPDATE cz_lce_load_specs SET deleted_flag = FLAG_NOT_DELETED
11183 WHERE lce_header_id = NewHeaders(i);
11184
11185 cz_security_pvt.unlock_model(1.0, FND_API.G_TRUE, l_locked_models, l_lock_status, l_msg_count, l_msg_data);
11186
11187 IF(l_lock_status <> FND_API.G_RET_STS_SUCCESS)THEN
11188 FOR jmessage IN 1..l_msg_count LOOP
11189 REPORT(fnd_msg_pub.get(jmessage, FND_API.G_FALSE), 0);
11190 END LOOP;
11191 END IF;
11192
11193 IF(TwoPhaseCommit = 0)THEN COMMIT; END IF;
11194 END;
11195 ---------------------------------------------------------------------------------------
11196 PROCEDURE ROLLBACK_HEADERS IS
11197 BEGIN
11198
11199 FORALL i IN 1..NewHeaders.COUNT
11200 UPDATE cz_lce_headers SET deleted_flag = FLAG_DELETED
11201 WHERE lce_header_id = NewHeaders(i);
11202
11203 FORALL i IN 1..NewHeaders.COUNT
11204 UPDATE cz_lce_load_specs SET deleted_flag = FLAG_DELETED
11205 WHERE lce_header_id = NewHeaders(i);
11206
11207 IF(OldHeaders.COUNT > 0)THEN
11208
11209 FORALL i IN 1..OldHeaders.COUNT
11210 UPDATE cz_lce_headers SET deleted_flag = FLAG_NOT_DELETED
11211 WHERE lce_header_id = OldHeaders(i);
11212
11213 FORALL i IN 1..OldHeaders.COUNT
11214 UPDATE cz_lce_load_specs SET deleted_flag = FLAG_NOT_DELETED
11215 WHERE lce_header_id = OldHeaders(i);
11216 END IF;
11217
11218 cz_security_pvt.unlock_model(1.0, FND_API.G_TRUE, l_locked_models, l_lock_status, l_msg_count, l_msg_data);
11219
11220 IF(l_lock_status <> FND_API.G_RET_STS_SUCCESS)THEN
11221 FOR jmessage IN 1..l_msg_count LOOP
11222 REPORT(fnd_msg_pub.get(jmessage, FND_API.G_FALSE), 0);
11223 END LOOP;
11224 END IF;
11225
11226 IF(TwoPhaseCommit = 0)THEN COMMIT; END IF;
11227
11228 EXCEPTION
11229 WHEN OTHERS THEN
11230 --'Fatal error. Logic header maintainance not completed. Unable to rollback changes because of %ERRORTEXT'
11231 REPORT(CZ_UTILS.GET_TEXT('CZ_G_UNABLE_TO_ROLLBACK', 'ERRORTEXT', SQLERRM), 0);
11232 END;
11233 ---------------------------------------------------------------------------------------
11234 FUNCTION CHECK_DATES(inModelId IN NUMBER, inLogicUpdate IN DATE, inHeaderCreated IN DATE)
11235 RETURN PLS_INTEGER IS
11236
11237 c_model refCursor;
11238 childFlag PLS_INTEGER;
11239 thisFlag PLS_INTEGER := GENERATION_NOT_REQUIRED;
11240 childModelId cz_devl_projects.devl_project_id%TYPE;
11241 childLogicUpdate cz_devl_projects.last_logic_update%TYPE;
11242 childHeaderCreated cz_lce_headers.creation_date%TYPE;
11243
11244 BEGIN
11245
11246 IF(NOT modelChecked.EXISTS(inModelId))THEN
11247
11248 modelChecked(inModelId) := 1;
11249
11250 OPEN c_model FOR logicSQL USING inModelId;
11251 LOOP
11252 FETCH c_model INTO childModelId, childLogicUpdate, childHeaderCreated;
11253 EXIT WHEN c_model%NOTFOUND;
11254
11255 childFlag := CHECK_DATES(childModelId, childLogicUpdate, childHeaderCreated);
11256
11257 IF(thisFlag = GENERATION_NOT_REQUIRED AND
11258 (childFlag = GENERATION_REQUIRED OR inHeaderCreated < childLogicUpdate))THEN
11259 thisFlag := GENERATION_REQUIRED;
11260 END IF;
11261 END LOOP;
11262 CLOSE c_model;
11263 END IF;
11264
11265 IF(thisFlag = GENERATION_NOT_REQUIRED AND inHeaderCreated < inLogicUpdate)THEN
11266 thisFlag := GENERATION_REQUIRED;
11267 END IF;
11268
11269 IF(thisFlag = GENERATION_NOT_REQUIRED)THEN
11270 IsLogicGenerated(inModelId) := 0;
11271 END IF;
11272 RETURN thisFlag;
11273 END;
11274 ---------------------------------------------------------------------------------------
11275 BEGIN --GENERATE_LOGIC_
11276
11277 --Bug #4587682. Save current nls numeric characters and set the standard characters.
11278
11279 SELECT value INTO StoreNlsCharacters FROM NLS_SESSION_PARAMETERS
11280 WHERE UPPER(parameter) = 'NLS_NUMERIC_CHARACTERS';
11281
11282 SET_NLS_CHARACTERS(NlsNumericCharacters);
11283
11284 BEGIN
11285
11286 --Database settings processing section
11287
11288 BEGIN
11289
11290 --Get the commit block size - the number of records inserted into cz_lce_texts
11291 --after which the transaction is commited, if commit is not disabled at all by
11292 --TwoPhaseCommit parameter set to 1.
11293
11294 SELECT TO_NUMBER(value) INTO CommitBlockSize
11295 FROM cz_db_settings
11296 WHERE LOWER(setting_id) = COMMIT_BLOCK_SETTING_ID
11297 AND LOWER(section_name) = DBSETTINGS_SECTION_NAME;
11298
11299 IF(CommitBlockSize <= 0) THEN CommitBlockSize := DEFAULT_COMMIT_BLOCK_SIZE; END IF;
11300
11301 EXCEPTION
11302 WHEN OTHERS THEN
11303 CommitBlockSize := DEFAULT_COMMIT_BLOCK_SIZE;
11304 END;
11305
11306 /* Making the optimizations unconditional, cz_db_settings ignored.
11307 BEGIN
11308
11309 --Get the NotTrue optimization flag, no optimization by default.
11310
11311 SELECT DECODE(LOWER(value), '1', 1, 'on', 1, 'y', 1, 'yes', 1,'true', 1, 'enable', 1,
11312 '0', 0, 'off', 0, 'n', 0, 'no', 0,'false', 0, 'disable', 0,
11313 0) --default value
11314 INTO OptimizeNotTrue
11315 FROM cz_db_settings
11316 WHERE LOWER(setting_id) = OPTIMIZE_NOTTRUE_SETTING_ID
11317 AND LOWER(section_name) = DBSETTINGS_SECTION_NAME;
11318
11319 EXCEPTION
11320 WHEN OTHERS THEN
11321 OptimizeNotTrue := 0;
11322 END;
11323
11324 BEGIN
11325
11326 --Get the AllOf/AnyOf optimization flag, no optimization by default.
11327
11328 SELECT DECODE(LOWER(value), '1', 1, 'on', 1, 'y', 1, 'yes', 1,'true', 1, 'enable', 1,
11329 '0', 0, 'off', 0, 'n', 0, 'no', 0,'false', 0, 'disable', 0,
11330 0) --default value
11331 INTO OptimizeAllAnyOf
11332 FROM cz_db_settings
11333 WHERE LOWER(setting_id) = OPTIMIZE_ALLANYOF_SETTING_ID
11334 AND LOWER(section_name) = DBSETTINGS_SECTION_NAME;
11335
11336 EXCEPTION
11337 WHEN OTHERS THEN
11338 OptimizeAllAnyOf := 0;
11339 END;
11340
11341 BEGIN
11342
11343 --Get the Change Children Order flag, no change by default.
11344 --Currently will change children order when generating AllOf/AnyOf.
11345
11346 SELECT DECODE(LOWER(value), '1', 1, 'on', 1, 'y', 1, 'yes', 1,'true', 1, 'enable', 1,
11347 '0', 0, 'off', 0, 'n', 0, 'no', 0,'false', 0, 'disable', 0,
11348 0) --default value
11349 INTO ChangeChildrenOrder
11350 FROM cz_db_settings
11351 WHERE LOWER(setting_id) = CHILDREN_ORDER_SETTING_ID
11352 AND LOWER(section_name) = DBSETTINGS_SECTION_NAME;
11353
11354 EXCEPTION
11355 WHEN OTHERS THEN
11356 ChangeChildrenOrder := 0;
11357 END;
11358 */
11359
11360 --Enable all three optimizations here ignoring cz_db_settings.
11361
11362 OptimizeNotTrue := 1;
11363 OptimizeAllAnyOf := 1;
11364 ChangeChildrenOrder := 1;
11365
11366 BEGIN
11367
11368 --See if we want to generate gated combinations, yes by default.
11369
11370 SELECT DECODE(LOWER(value), '1', 1, 'on', 1, 'y', 1, 'yes', 1,'true', 1, 'enable', 1,
11371 '0', 0, 'off', 0, 'n', 0, 'no', 0,'false', 0, 'disable', 0,
11372 1) --default value
11373 INTO GenerateGatedCombo
11374 FROM cz_db_settings
11375 WHERE LOWER(setting_id) = GATED_COMBO_SETTING_ID
11376 AND LOWER(section_name) = DBSETTINGS_SECTION_NAME;
11377
11378 EXCEPTION
11379 WHEN OTHERS THEN
11380 GenerateGatedCombo := 1;
11381 END;
11382
11383 BEGIN
11384
11385 --See if we want to stop when a fatal rule error is encountered, yes by default.
11386
11387 SELECT DECODE(LOWER(value), '1', 1, 'on', 1, 'y', 1, 'yes', 1,'true', 1, 'enable', 1,
11388 '0', 0, 'off', 0, 'n', 0, 'no', 0,'false', 0, 'disable', 0,
11389 1) --default value
11390 INTO StopOnFatalRuleError
11391 FROM cz_db_settings
11392 WHERE LOWER(setting_id) = STOP_ON_ERROR_SETTING_ID
11393 AND LOWER(section_name) = DBSETTINGS_SECTION_NAME;
11394
11395 EXCEPTION
11396 WHEN OTHERS THEN
11397 StopOnFatalRuleError := 1;
11398 END;
11399
11400 BEGIN
11401
11402 --See if we want to generate logic only for updated models, yes by default.
11403
11404 SELECT DECODE(LOWER(value), '1', 1, 'on', 1, 'y', 1, 'yes', 1,'true', 1, 'enable', 1,
11405 '0', 0, 'off', 0, 'n', 0, 'no', 0,'false', 0, 'disable', 0,
11406 1) --default value
11407 INTO GenerateUpdatedOnly
11408 FROM cz_db_settings
11409 WHERE LOWER(setting_id) = UPDATED_ONLY_SETTING_ID
11410 AND LOWER(section_name) = DBSETTINGS_SECTION_NAME;
11411
11412 EXCEPTION
11413 WHEN OTHERS THEN
11414 GenerateUpdatedOnly := 1;
11415 END;
11416
11417 --Get the logic generation run id. If a valid value has been passed as a parameter, use it,
11418 --else generate a new value.
11419
11420 IF(thisRunId IS NULL OR thisRunId = 0)THEN
11421 SELECT cz_xfr_run_infos_s.NEXTVAL INTO thisRunId FROM DUAL;
11422 END IF;
11423
11424 --Read the cz_effectivity_sets table into memory and create hash tables for
11425 --effectivity dates
11426
11427 -- Bug10407496 : Selecting only effectivity sets belongs repository
11428
11429 SELECT effectivity_set_id, effective_from, effective_until
11430 BULK COLLECT INTO gvSetId, gvEffFrom, gvEffUntil
11431 FROM cz_effectivity_sets
11432 WHERE deleted_flag = FLAG_NOT_DELETED
11433 AND EXISTS (SELECT null FROM cz_rp_entries
11434 WHERE object_type='EFF'
11435 AND deleted_flag = FLAG_NOT_DELETED
11436 AND object_id = effectivity_set_id);
11437
11438 --Add the indexing option
11439
11440 IF(gvSetId.LAST IS NOT NULL)THEN
11441 FOR i IN gvSetId.FIRST..gvSetId.LAST LOOP
11442 gvIndexBySetId(gvSetId(i)) := i;
11443 END LOOP;
11444 END IF;
11445
11446 --This block is introduced to implement locking.
11447
11448 BEGIN
11449
11450 l_locked_models.DELETE;
11451 cz_security_pvt.lock_model(1.0, inDevlProjectId, FND_API.G_TRUE, FND_API.G_TRUE, l_locked_models, l_lock_status, l_msg_count, l_msg_data);
11452
11453 IF(l_lock_status <> FND_API.G_RET_STS_SUCCESS)THEN
11454 RAISE FAILED_TO_LOCK_MODEL;
11455 END IF;
11456
11457 --To disable this functionality, comment out the following IF block. Previously, we
11458 --could not correctly handle accumulators and NOTTRUE operator, for which we needed
11459 --to modify a child structure file even if it was up-to-date.
11460
11461 --Pre-populate the list of models that don't need to be regenerated because logic exists
11462 --and satisfies the 'up-to-date' criterion. Part of the fix for the bug #1941626.
11463 --For debugging purposes it may be convenient to be able to regenerate logic without any
11464 --dependency on the dates - the old way. A db setting is provided for that.
11465
11466 IF(GenerateUpdatedOnly = 1)THEN
11467
11468 --Have to always generate logic for the root model because the trigger updating
11469 --last_logic_update column is commented out on cz_expression_nodes, and this is
11470 --the only table Developer updates for some rule changes.
11471 --This is why we do not care about the return value and pass the margin reverse
11472 --dates.
11473
11474 nParam := CHECK_DATES(inDevlProjectId, EpochEndDate, EpochBeginDate);
11475 END IF;
11476
11477 globalLevel := globalLevel + 1;
11478 globalStack(globalLevel) := inDevlProjectId;
11479 globalRef(globalLevel) := inDevlProjectId;
11480 globalInstance(globalLevel) := 0;
11481
11482 --Start off the recursion
11483
11484 GENERATE_COMPONENT_TREE(inDevlProjectId, inDevlProjectId, NULL);
11485
11486 --LCE header maintainance
11487
11488 COMMIT_HEADERS;
11489
11490 EXCEPTION
11491 WHEN FAILED_TO_LOCK_MODEL THEN
11492
11493 FOR jmessage IN 1..l_msg_count LOOP
11494 REPORT(fnd_msg_pub.get(jmessage, FND_API.G_FALSE), 0);
11495 END LOOP;
11496
11497 ROLLBACK_HEADERS;
11498 WHEN OTHERS THEN
11499 RAISE;
11500 END;
11501
11502 --Handle here the exceptions that should terminate the logic tree generation process.
11503
11504 EXCEPTION
11505 WHEN CZ_S_UNABLE_TO_CREATE_HEADER THEN
11506 --'Unable to create logic header because of %ERRORTEXT'
11507 REPORT(CZ_UTILS.GET_TEXT('CZ_G_UNABLE_TO_CREATE_HEADER', 'ERRORTEXT', errorMessage), 0);
11508 ROLLBACK_HEADERS;
11509 WHEN CZ_R_UNABLE_TO_CREATE_HEADER THEN
11510 --'Unable to create logic header because of %ERRORTEXT'
11511 REPORT(CZ_UTILS.GET_TEXT('CZ_G_UNABLE_TO_CREATE_HEADER', 'ERRORTEXT', errorMessage), 0);
11512 ROLLBACK_HEADERS;
11513 WHEN CZ_S_DEADLOOP_DETECTED THEN
11514 REPORT(errorMessage, 0);
11515 ROLLBACK_HEADERS;
11516 WHEN CZ_S_UNKNOWN_FEATURE_TYPE THEN
11517 REPORT(errorMessage, 0);
11518 ROLLBACK_HEADERS;
11519 WHEN CZ_S_UNKNOWN_NODE_TYPE THEN
11520 REPORT(errorMessage, 0);
11521 ROLLBACK_HEADERS;
11522 WHEN CZ_S_UNKNOWN_BOM_NODE_TYPE THEN
11523 REPORT(errorMessage, 0);
11524 ROLLBACK_HEADERS;
11525 WHEN CZ_S_TOO_MANY_OPTIONS THEN
11526 REPORT(errorMessage, 0);
11527 ROLLBACK_HEADERS;
11528 WHEN CZ_S_WRONG_EFFECTIVITY_SET THEN
11529 REPORT(errorMessage, 0);
11530 ROLLBACK_HEADERS;
11531 WHEN CZ_S_INCONSISTENT_QUANTITY THEN
11532 REPORT(errorMessage, 0);
11533 ROLLBACK_HEADERS;
11534 WHEN CZ_S_INCORRECT_QUANTITY THEN
11535 --'BOM item ''%ITEMNAME'' cannot have default quantity greater than 1 because it contains other trackable BOM items.'
11536 REPORT(CZ_UTILS.GET_TEXT('CZ_S_INCORRECT_QUANTITY', 'ITEMNAME', glName(nParam)), 0);
11537 ROLLBACK_HEADERS;
11538 WHEN CZ_S_TRACKABLE_CHILDREN THEN
11539 --'Invalid Model structure: ''%CHILDNAME'' is a direct child of ''%MODELNAME''. A trackable BOM item cannot be a direct child of a Container Model.'
11540 REPORT(CZ_UTILS.GET_TEXT('CZ_S_TRACKABLE_CHILDREN', 'CHILDNAME', glName(nParam), 'MODELNAME', errorMessage), 0);
11541 ROLLBACK_HEADERS;
11542 WHEN CZ_S_TRACKABLE_STANDARD THEN
11543 --'Invalid Model structure: ''%CHILDNAME'' is a direct child of ''%MODELNAME''. A trackable Standard Item cannot be
11544 -- a direct child of a non-trackable ATO or PTO BOM Model that is referenced by a Container Model.'
11545 REPORT(CZ_UTILS.GET_TEXT('CZ_S_TRACKABLE_STANDARD', 'CHILDNAME', glName(nParam), 'MODELNAME', errorMessage), 0);
11546 ROLLBACK_HEADERS;
11547 WHEN CZ_S_MULTIPLE_TRACKABLE THEN
11548 --'Invalid Model structure: Multiple references exist to the trackable instance ''%CHILDNAME''.'
11549 REPORT(CZ_UTILS.GET_TEXT('CZ_S_MULTIPLE_TRACKABLE', 'CHILDNAME', errorMessage), 0);
11550 ROLLBACK_HEADERS;
11551 WHEN CZ_S_MULTIPLE_INSTANCES THEN
11552 --'Invalid Model structure: The non-trackable Model ''%MODELNAME'' cannot have multiple instances because it is not a descendent of a trackable Model and it
11553 -- contains the trackable Model ''%CHILDNAME''. Please set both the Instances Minimum and Maximum fields for ''%MODELNAME'' to 1.'
11554 REPORT(CZ_UTILS.GET_TEXT('CZ_S_MULTIPLE_INSTANCES', 'CHILDNAME', errorMessage, 'MODELNAME', glName(nParam)), 0);
11555 ROLLBACK_HEADERS;
11556 WHEN CZ_S_CONNECT_NONTRACKABLE THEN
11557 --'Invalid Connector: Connector to non-trackable Model ''%CHILDNAME'' from the trackable Model ''%MODELNAME''. A Connector from a non-trackable Model
11558 -- to a trackable Model is not allowed in a Container Model.'
11559 REPORT(CZ_UTILS.GET_TEXT('CZ_S_CONNECT_NONTRACKABLE', 'CHILDNAME', errorMessage, 'MODELNAME', glName(nParam)), 0);
11560 ROLLBACK_HEADERS;
11561 WHEN CZ_S_CONTAINER_REFERENCE THEN
11562 --'Invalid Reference: Model ''%MODELNAME'' references the Model ''%CHILDNAME''. A Container Model cannot reference another Container Model.'
11563 REPORT(CZ_UTILS.GET_TEXT('CZ_S_CONTAINER_REFERENCE', 'CHILDNAME', errorMessage, 'MODELNAME', rootProjectName), 0);
11564 ROLLBACK_HEADERS;
11565 WHEN CZ_S_CONNECTOR_TRACKABLE THEN
11566 --'The Connector from ''%MODELNAME'' to the trackable Model ''%CHILDNAME'' is not allowed because no ancestor of ''%MODELNAME'' is trackable.'
11567 REPORT(CZ_UTILS.GET_TEXT('CZ_S_CONNECTOR_TRACKABLE', 'CHILDNAME', glName(nParam), 'MODELNAME', errorMessage), 0);
11568 ROLLBACK_HEADERS;
11569 WHEN CZ_S_INCORRECT_CONTAINER THEN
11570 --'The Reference to trackable Model ''%CHILDNAME'' in the Container Model ''%MODELNAME'' has an invalid number
11571 -- of Instances specified. Please set Minimum Instances to 0 and Maximum Instances to Null for this node,
11572 -- then regenerate the Active Model.'
11573 REPORT(CZ_UTILS.GET_TEXT('CZ_S_INCORRECT_CONTAINER', 'CHILDNAME', errorMessage, 'MODELNAME', rootProjectName), 0);
11574 ROLLBACK_HEADERS;
11575 WHEN CZ_S_NO_TRACKABLE_FLAG THEN
11576 --'Trackable status is undefined for the Model ''%CHILDNAME'' in the Container Model ''%MODELNAME''.
11577 -- Please refresh the Model by running the Refresh a Single Configuration Model concurrent program
11578 -- and then regenerate the Active Model.'
11579 REPORT(CZ_UTILS.GET_TEXT('CZ_S_NO_TRACKABLE_FLAG', 'CHILDNAME', errorMessage, 'MODELNAME', rootProjectName), 0);
11580 ROLLBACK_HEADERS;
11581 WHEN CZ_S_NO_DATA_IN_PROJECT THEN
11582 --'Project ''%PROJECTNAME'' contains no data, no logic generated'
11583 REPORT(CZ_UTILS.GET_TEXT('CZ_S_NO_DATA_IN_PROJECT', 'PROJECTNAME', errorMessage), 0);
11584 ROLLBACK_HEADERS;
11585 WHEN CZ_S_NO_SUCH_PROJECT THEN
11586 --'Project does not exist for the specified ID: %PROJECTID. No logic generated.'
11587 REPORT(CZ_UTILS.GET_TEXT('CZ_S_NO_SUCH_PROJECT', 'PROJECTID', nParam), 0);
11588 ROLLBACK_HEADERS;
11589 WHEN CZ_S_TRACKABLE_CONTAINER THEN
11590 --'Error in Model ''%PROJECTNAME'': A trackable Model cannot be a Container Model.'
11591 REPORT(CZ_UTILS.GET_TEXT('CZ_S_TRACKABLE_CONTAINER', 'PROJECTNAME', errorMessage), 0);
11592 ROLLBACK_HEADERS;
11593 WHEN CZ_LCE_MODEL_OUTOFDATE THEN
11594 --'The BOM Model ''%MODELNAME'' is out of date. Please refresh the Model by running the Refresh a Single
11595 -- Configuration Model concurrent program and then regenerate the Active Model.'
11596 REPORT(CZ_UTILS.GET_TEXT('CZ_LCE_MODEL_OUTOFDATE', 'MODELNAME', errorMessage), 0);
11597 ROLLBACK_HEADERS;
11598 WHEN CZ_LCE_INCORRECT_BOM THEN
11599 --'Incorrect BOM Model or Option Class ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
11600 -- Only BOM Standard Items can be shippable and inventory transactable.'
11601 REPORT(CZ_UTILS.GET_TEXT('CZ_LCE_INCORRECT_BOM', 'NODENAME', thisName, 'PARENTNAME', parentName, 'MODELNAME', errorMessage), 0);
11602 ROLLBACK_HEADERS;
11603 WHEN CZ_LCE_INCORRECT_ITEM THEN
11604 --'Incorrect BOM Standard Item ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
11605 -- All shippable items should be inventory transactable and vice versa.'
11606 REPORT(CZ_UTILS.GET_TEXT('CZ_LCE_INCORRECT_ITEM', 'NODENAME', thisName, 'PARENTNAME', parentName, 'MODELNAME', errorMessage), 0);
11607 ROLLBACK_HEADERS;
11608 WHEN CZ_LCE_INCORRECT_TANGIBLE THEN
11609 --'Incorrect BOM Standard Item ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
11610 -- All shippable items should be trackable non-ATO standard items with maximum quantity 1.'
11611 REPORT(CZ_UTILS.GET_TEXT('CZ_LCE_INCORRECT_TANGIBLE', 'NODENAME', thisName, 'PARENTNAME', parentName, 'MODELNAME', errorMessage), 0);
11612 ROLLBACK_HEADERS;
11613 WHEN CZ_LCE_INCORRECT_SHIPPABLE THEN
11614 --'Incorrect BOM Standard Item ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
11615 -- All shippable items should be serializable trackable non-ATO standard items.'
11616 REPORT(CZ_UTILS.GET_TEXT('CZ_LCE_INCORRECT_SHIPPABLE', 'NODENAME', thisName, 'PARENTNAME', parentName, 'MODELNAME', errorMessage), 0);
11617 ROLLBACK_HEADERS;
11618 WHEN CZ_G_INVALID_RULE_EXPLOSION THEN
11619 --'Internal data error. Unable to continue because of invalid data in rule ''%RULENAME''. Disable or delete the rule to generate logic.'
11620 errorMessage := CZ_UTILS.GET_TEXT('CZ_G_INVALID_RULE_EXPLOSION', 'RULENAME', errorMessage);
11621 REPORT(errorMessage, 0);
11622 ROLLBACK_HEADERS;
11623 WHEN CZ_G_INVALID_MODEL_EXPLOSION THEN
11624 --'Internal data error. Unable to continue because of invalid data in model ''%MODELNAME'' - loop detected.'
11625 errorMessage := CZ_UTILS.GET_TEXT('CZ_G_INVALID_MODEL_EXPLOSION', 'MODELNAME', errorMessage);
11626 REPORT(errorMessage, 0);
11627 ROLLBACK_HEADERS;
11628 WHEN CZ_G_INVALID_EXPLOSION_TYPE THEN
11629 --'Internal data error. Unable to continue because of invalid data in the model ''%MODELNAME'' - incorrect explosion type.'
11630 errorMessage := CZ_UTILS.GET_TEXT('CZ_G_INVALID_EXPLOSION_TYPE', 'MODELNAME', errorMessage);
11631 REPORT(errorMessage, 0);
11632 ROLLBACK_HEADERS;
11633 WHEN OTHERS THEN
11634 IF(nDebug = 1 OR (nDebug >= 1000001 AND nDebug <= 1000011))THEN
11635 --'Unable to continue because of %ERRORTEXT. Reference explosions table may not be populated properly for model ''%MODELNAME'''
11636 errorMessage := CZ_UTILS.GET_TEXT('CZ_G_ERROR_IN_EXPLOSION', 'ERRORTEXT', SQLERRM, 'MODELNAME', glName(glIndexByPsNodeId(inDevlProjectId)));
11637 ELSIF(nDebug >= 40 AND nDebug <= 54)THEN
11638 --'Internal data error. Unable to continue because of invalid data in rule ''%RULENAME''. Disable or delete the rule to generate logic.'
11639 errorMessage := CZ_UTILS.GET_TEXT('CZ_G_INVALID_RULE_EXPLOSION', 'RULENAME', errorMessage);
11640 ELSIF(SUBSTR(TO_CHAR(nDebug), 1, 1) = '8')THEN
11641 --'Unable to continue because of %ERRORTEXT: (nRuleId)'
11642 errorMessage := CZ_UTILS.GET_TEXT('CZ_G_GENERAL_ERROR', 'ERRORTEXT', SQLERRM || ': (' || errorMessage || ')');
11643 ELSE
11644 --'Unable to continue because of %ERRORTEXT'
11645 errorMessage := CZ_UTILS.GET_TEXT('CZ_G_GENERAL_ERROR', 'ERRORTEXT', SQLERRM);
11646 END IF;
11647 REPORT(errorMessage, 0);
11648 ROLLBACK_HEADERS;
11649 END;
11650
11651 --Bug #4587682. Restore the session's nls numeric characters.
11652
11653 SET_NLS_CHARACTERS(StoreNlsCharacters);
11654
11655 EXCEPTION
11656 WHEN OTHERS THEN
11657 SET_NLS_CHARACTERS(StoreNlsCharacters);
11658 RAISE;
11659 END; --GENERATE_MODEL_TREE
11660 ---------------------------------------------------------------------------------------
11661 --An additional entry point for those callers who cannot handle defaulted parameters---
11662
11663 PROCEDURE GENERATE_LOGIC(inDevlProjectId IN NUMBER,
11664 thisRunId IN OUT NOCOPY NUMBER)
11665 IS
11666
11667 l_config_engine_type cz_devl_projects.config_engine_type%TYPE;
11668 l_fusion_debug VARCHAR2(240);
11669
11670 BEGIN
11671
11672 BEGIN
11673
11674 SELECT config_engine_type INTO l_config_engine_type
11675 FROM cz_devl_projects
11676 WHERE deleted_flag = FLAG_NOT_DELETED
11677 AND devl_project_id = inDevlProjectId;
11678
11679 EXCEPTION
11680 WHEN NO_DATA_FOUND THEN
11681 l_config_engine_type := 'L';
11682 END;
11683
11684 IF ( l_config_engine_type = 'F') THEN
11685
11686 l_fusion_debug := NVL ( fnd_profile.value_wnps ('CZ_DEV_FCE_DEBUG_LOGIC'), 'N');
11687
11688 IF ( l_fusion_debug = 'N' ) THEN
11689
11690 cz_fce_compile.compile_logic ( inDevlProjectId, thisRunId );
11691
11692 ELSE
11693
11694 cz_fce_compile.debug_logic ( inDevlProjectId, thisRunId );
11695
11696 END IF;
11697
11698 ELSE
11699
11700 GENERATE_LOGIC_(inDevlProjectId, thisRunId, 0);
11701
11702 END IF;
11703 END;
11704 ---------------------------------------------------------------------------------------
11705 --This entry makes the logic generation work remotely in a distributed transaction,even
11706 --if the model contains property-based compatibility rules - bug #2028790.
11707 --DDL used in the property-based compatibility rules makes implicit commits and commits
11708 --are not allowed in a distributed transaction when the remote procedure has parameters
11709 --of type OUT.
11710
11711 PROCEDURE GENERATE_LOGIC__(inDevlProjectId IN NUMBER,
11712 thisRunId IN NUMBER)
11713 IS
11714 outRunId NUMBER := thisRunId;
11715 BEGIN
11716 GENERATE_LOGIC_(inDevlProjectId, outRunId, 1);
11717 END;
11718 ---------------------------------------------------------------------------------------
11719 BEGIN
11720
11721 OperatorLiterals(OPERATOR_ADD) := ' + ';
11722 OperatorLiterals(OPERATOR_SUB) := ' - ';
11723 OperatorLiterals(OPERATOR_MULT) := ' * ';
11724 OperatorLiterals(OPERATOR_DIV) := ' / ';
11725 OperatorLiterals(OPERATOR_EQUALS) := ' = ';
11726 OperatorLiterals(OPERATOR_NOTEQUALS) := ' != ';
11727 OperatorLiterals(OPERATOR_GT) := ' > ';
11728 OperatorLiterals(OPERATOR_LT) := ' < ';
11729 OperatorLiterals(OPERATOR_GE) := ' >= ';
11730 OperatorLiterals(OPERATOR_LE) := ' <= ';
11731 OperatorLiterals(OPERATOR_ADD_INT) := ' + ';
11732 OperatorLiterals(OPERATOR_SUB_INT) := ' - ';
11733 OperatorLiterals(OPERATOR_MULT_INT) := ' * ';
11734 OperatorLiterals(OPERATOR_EQUALS_INT) := ' = ';
11735 OperatorLiterals(OPERATOR_NOTEQUALS_INT) := ' != ';
11736 OperatorLiterals(OPERATOR_GT_INT) := ' > ';
11737 OperatorLiterals(OPERATOR_LT_INT) := ' < ';
11738 OperatorLiterals(OPERATOR_GE_INT) := ' >= ';
11739 OperatorLiterals(OPERATOR_LE_INT) := ' <= ';
11740 OperatorLiterals(OPERATOR_POW_INT) := ' POW ';
11741 OperatorLiterals(OPERATOR_ROUND) := ' ROUND ';
11742 OperatorLiterals(OPERATOR_CEILING) := ' CEILING ';
11743 OperatorLiterals(OPERATOR_FLOOR) := ' FLOOR ';
11744 OperatorLiterals(OPERATOR_TRUNCATE) := ' TRUNCATE ';
11745 OperatorLiterals(OPERATOR_MIN) := ' MIN ';
11746 OperatorLiterals(OPERATOR_MAX) := ' MAX ';
11747 OperatorLiterals(OPERATOR_AND) := ' AND ';
11748 OperatorLiterals(OPERATOR_OR) := ' OR ';
11749 OperatorLiterals(OPERATOR_NOT) := ' NOT ';
11750 OperatorLiterals(OPERATOR_NOTTRUE) := ' NOTTRUE ';
11751 OperatorLiterals(OPERATOR_COS) := ' COS ';
11752 OperatorLiterals(OPERATOR_ACOS) := ' ACOS ';
11753 OperatorLiterals(OPERATOR_COSH) := ' COSH ';
11754 OperatorLiterals(OPERATOR_SIN) := ' SIN ';
11755 OperatorLiterals(OPERATOR_ASIN) := ' ASIN ';
11756 OperatorLiterals(OPERATOR_SINH) := ' SINH ';
11757 OperatorLiterals(OPERATOR_TAN) := ' TAN ';
11758 OperatorLiterals(OPERATOR_ATAN) := ' ATAN ';
11759 OperatorLiterals(OPERATOR_TANH) := ' TANH ';
11760 OperatorLiterals(OPERATOR_LOG) := ' LOG ';
11761 OperatorLiterals(OPERATOR_LOG10) := ' LOG10 ';
11762 OperatorLiterals(OPERATOR_EXP) := ' EXP ';
11763 OperatorLiterals(OPERATOR_ABS) := ' ABS ';
11764 OperatorLiterals(OPERATOR_SQRT) := ' SQRT ';
11765 OperatorLiterals(OPERATOR_MATHDIV) := ' DIV ';
11766 OperatorLiterals(OPERATOR_POW) := ' POW ';
11767 OperatorLiterals(OPERATOR_ATAN2) := ' ATAN2 ';
11768 OperatorLiterals(OPERATOR_MOD) := ' MOD ';
11769 OperatorLiterals(OPERATOR_ROUNDTONEAREST) := ' ROUND ';
11770 OperatorLiterals(OPERATOR_ROUNDUPTONEAREST) := ' CEILING ';
11771 OperatorLiterals(OPERATOR_ROUNDDOWNTONEAREST) := ' FLOOR ';
11772 OperatorLiterals(OPERATOR_ALLOF) := ' All True ';
11773 OperatorLiterals(OPERATOR_ANYOF) := ' Any True ';
11774 OperatorLiterals(OPERATOR_NONE) := ' ';
11775
11776 OperatorLetters(OPERATOR_AND) := ' L ';
11777 OperatorLetters(OPERATOR_OR) := ' N ';
11778 OperatorLetters(OPERATOR_ALLOF) := ' L ';
11779 OperatorLetters(OPERATOR_ANYOF) := ' N ';
11780 OperatorLetters(RULE_OPERATOR_REQUIRES) := ' R ';
11781 OperatorLetters(RULE_OPERATOR_IMPLIES) := ' I ';
11782 OperatorLetters(RULE_OPERATOR_EXCLUDES) := ' E ';
11783 OperatorLetters(RULE_OPERATOR_NEGATES) := ' N ';
11784
11785 CodeByCodeLookup(TEMPLATE_ANYTRUE) := OPERATOR_ANYOF;
11786 CodeByCodeLookup(TEMPLATE_ALLTRUE) := OPERATOR_ALLOF;
11787 END;