1 PACKAGE BODY CZ_LOGIC_GEN AS
2 /* $Header: czlcegnb.pls 120.33.12010000.2 2008/10/21 19:31:20 asiaston 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.33.12010000.2 2008/10/21 19:31:20 asiaston 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 logicSQL VARCHAR2(4000) := 'SELECT proj.devl_project_id, proj.last_logic_update, head.creation_date' ||
207 ' FROM cz_devl_projects proj, cz_model_ref_expls expl, cz_lce_headers head' ||
208 ' WHERE proj.deleted_flag = ''' || FLAG_NOT_DELETED ||
209 ''' AND expl.deleted_flag = ''' || FLAG_NOT_DELETED ||
210 ''' AND head.deleted_flag = ''' || FLAG_NOT_DELETED ||
211 ''' AND expl.node_depth = 1' ||
212 ' AND expl.model_id = :1' ||
213 ' AND head.net_type = 1' ||
214 ' AND proj.devl_project_id = expl.component_id' ||
215 ' AND proj.devl_project_id = head.component_id';
216
217 h_containerReferred tIntegerArray_idx_vc2;
218 containerReferred VARCHAR2(4000) :=
219
220 'SELECT 1 FROM DUAL WHERE EXISTS' ||
221 ' (SELECT model_id FROM cz_model_ref_expls' ||
222 ' WHERE deleted_flag = ''' || FLAG_NOT_DELETED || '''' ||
223 ' AND ps_node_type IN (' || PS_NODE_TYPE_REFERENCE || ', ' || PS_NODE_TYPE_CONNECTOR || ')' ||
224 ' AND component_id = :1' ||
225 ' AND (SELECT model_type FROM cz_devl_projects' ||
226 ' WHERE devl_project_id = model_id) = ''' || MODEL_TYPE_CONTAINER_MODEL || ''')';
227
228 GENERATION_REQUIRED CONSTANT PLS_INTEGER := 1;
229 GENERATION_NOT_REQUIRED CONSTANT PLS_INTEGER := 2;
230
231 table_name_generator PLS_INTEGER := 1;
232 table_hash_propval tVarcharHashType;
233 ---------------------------------------------------------------------------------------
234 --Bug #5727549.
235
236 last_id_allocated NUMBER := NULL;
237 next_id_to_use NUMBER := 0;
238
239 FUNCTION next_lce_header_id RETURN NUMBER IS
240 id_to_return NUMBER;
241 BEGIN
242 IF((last_id_allocated IS NULL) OR
243 (next_id_to_use = (NVL(last_id_allocated, 0) + CZ_SEQUENCE_INCREMENT)))THEN
244
245 SELECT cz_lce_headers_s.NEXTVAL INTO last_id_allocated FROM DUAL;
246 next_id_to_use := last_id_allocated;
247 END IF;
248
249 id_to_return := next_id_to_use;
250 next_id_to_use := next_id_to_use + 1;
251 RETURN id_to_return;
252 END next_lce_header_id;
253 ---------------------------------------------------------------------------------------
254 --Reporting procedure
255
256 PROCEDURE REPORT(inMessage IN VARCHAR2, inUrgency IN PLS_INTEGER) IS
257 BEGIN
258
259 INSERT INTO cz_db_logs (message, statuscode, caller, urgency, run_id)
260 VALUES (inMessage, nDebug, 'Logic Generator', inUrgency, thisRunId);
261
262 EXCEPTION
263 WHEN OTHERS THEN
264 RAISE CZ_G_UNABLE_TO_REPORT_ERROR;
265 END;
266 ---------------------------------------------------------------------------------------
267 PROCEDURE SET_NLS_CHARACTERS(p_nls_characters IN VARCHAR2) IS
268 BEGIN
269 IF(NlsNumericCharacters <> StoreNlsCharacters)THEN
270
271 EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_NUMERIC_CHARACTERS = ''' || p_nls_characters || '''';
272 END IF;
273 END;
274 ---------------------------------------------------------------------------------------
275 PROCEDURE GENERATE_COMPONENT_TREE(inComponentId IN NUMBER,
276 inProjectId IN NUMBER,
277 inParentLogicHeaderId IN NUMBER)
278 IS
279
280 TYPE tNodeDepth IS TABLE OF cz_model_ref_expls.node_depth%TYPE INDEX BY BINARY_INTEGER;
281 TYPE tNodeType IS TABLE OF cz_model_ref_expls.ps_node_type%TYPE INDEX BY BINARY_INTEGER;
282 TYPE tVirtualFlag IS TABLE OF cz_model_ref_expls.virtual_flag%TYPE INDEX BY BINARY_INTEGER;
283 TYPE tParentId IS TABLE OF cz_model_ref_expls.component_id%TYPE INDEX BY BINARY_INTEGER;
284 TYPE tPsNodeId IS TABLE OF cz_model_ref_expls.component_id%TYPE INDEX BY BINARY_INTEGER;
285 TYPE tChildModelExpl IS TABLE OF cz_model_ref_expls.child_model_expl_id%TYPE INDEX BY BINARY_INTEGER;
286 TYPE tExplNodeType IS TABLE OF cz_model_ref_expls.expl_node_type%TYPE INDEX BY BINARY_INTEGER;
287 --kdande; Bug 6881902; 11-Mar-2008; Made the following PLSQL types local to the procedure as they are used for Bulk Collects
288 TYPE tPsNodeType IS TABLE OF cz_ps_nodes.ps_node_type%TYPE INDEX BY BINARY_INTEGER;
289 TYPE tReferenceId IS TABLE OF cz_ps_nodes.reference_id%TYPE INDEX BY BINARY_INTEGER;
290 TYPE tDecimalQty IS TABLE OF cz_ps_nodes.decimal_qty_flag%TYPE INDEX BY BINARY_INTEGER;
291 TYPE tIbTrackable IS TABLE OF cz_ps_nodes.ib_trackable%TYPE INDEX BY BINARY_INTEGER;
292 TYPE tAccumulator IS TABLE OF cz_ps_nodes.accumulator_flag%TYPE INDEX BY BINARY_INTEGER;
293 TYPE tInstantiableFlag IS TABLE OF cz_ps_nodes.instantiable_flag%TYPE INDEX BY BINARY_INTEGER;
294 TYPE tFeatureType IS TABLE OF cz_ps_nodes.feature_type%TYPE INDEX BY BINARY_INTEGER;
295 TYPE tName IS TABLE OF cz_ps_nodes.name%TYPE INDEX BY BINARY_INTEGER;
296 TYPE tInitialValue IS TABLE OF cz_ps_nodes.initial_value%TYPE INDEX BY BINARY_INTEGER;
297 TYPE tMinimum IS TABLE OF cz_ps_nodes.minimum%TYPE INDEX BY BINARY_INTEGER;
298 TYPE tMaximum IS TABLE OF cz_ps_nodes.maximum%TYPE INDEX BY BINARY_INTEGER;
299 TYPE tMinimumSel IS TABLE OF cz_ps_nodes.minimum_selected%TYPE INDEX BY BINARY_INTEGER;
300 TYPE tMaximumSel IS TABLE OF cz_ps_nodes.maximum_selected%TYPE INDEX BY BINARY_INTEGER;
301
302 ntPsNodeId tPsNodeId;
303 ntItemId tItemId;
304 ntPersistentId tPersistentId;
305 ntPsNodeType tPsNodeType;
306 ntInitialValue tInitialValue;
307 ntParentId tParentId;
308 ntMinimum tMinimum;
309 ntMaximum tMaximum;
310 ntVirtualFlag tVirtualFlag;
311 ntFeatureType tFeatureType;
312 ntName tName;
313 ntDescriptionId tDescriptionId;
314 ntMinimumSel tMinimumSel;
315 ntMaximumSel tMaximumSel;
316 ntBomRequired tBomRequired;
317 ntReferenceId tReferenceId;
318 dtEffFrom tDateArray;
319 dtEffUntil tDateArray;
320 vtUsageMask tUsageMask;
321 ntEffSetId tSetEffId;
322 ntDecimalQty tDecimalQty;
323 ntIbTrackable tIbTrackable;
324 ntAccumulator tAccumulator;
325 ntInitialNumValue tInitialNumValue;
326 ntInstantiableFlag tInstantiableFlag;
327 ntShippableFlag tShippableFlag;
328 ntTransactableFlag tTransactableFlag;
329 ntAtoFlag tAtoFlag;
330 ntSerializableFlag tSerializableFlag;
331
332 v_tNodeDepth tNodeDepth;
333 v_tNodeType tNodeType;
334 v_tVirtualFlag tVirtualFlag;
335 v_tParentId tParentId;
336 v_tPsNodeId tPsNodeId;
337 v_tReferringId tPsNodeId;
338 v_tChildModelExpl tChildModelExpl;
339 v_tExplNodeType tExplNodeType;
340 v_NodeId tExplNodeId;
341
342 v_IndexByNodeId tIntegerArray_idx_vc2;
343 v_TypeByExplId tExplNodeType;
344
345 thisComponentExplId cz_model_ref_expls.model_ref_expl_id%TYPE;
346 thisProjectId cz_devl_projects.devl_project_id%TYPE;
347 thisProjectName cz_devl_projects.name%TYPE;
348 thisProjectType cz_devl_projects.model_type%TYPE;
349 thisRootExplIndex PLS_INTEGER;
350
351 nStructureHeaderId cz_lce_headers.lce_header_id%TYPE;
352 PrevEffFrom DATE := EpochBeginDate;
353 PrevEffUntil DATE := EpochEndDate;
354 PrevUsageMask cz_ps_nodes.effective_usage_mask%TYPE := AnyUsageMask;
355 CurrentEffFrom DATE;
356 CurrentEffUntil DATE;
357 CurrentUsageMask cz_ps_nodes.effective_usage_mask%TYPE;
358 FeatureEffFrom DATE;
359 FeatureEffUntil DATE;
360 FeatureUsageMask cz_ps_nodes.effective_usage_mask%TYPE;
361 nSequenceNbr NUMBER := 1;
362 vLogicText VARCHAR2(4000);
363 vLogicLine VARCHAR2(4000);
364 vLogicName VARCHAR2(4000);
365
366 CurrentFromDate VARCHAR2(25);
367 CurrentUntilDate VARCHAR2(25);
368 localMinString VARCHAR2(25);
369 localMaxString VARCHAR2(25);
370
371 CurrentlyPacking PLS_INTEGER;
372 LastPacked PLS_INTEGER := PACKING_GENERIC;
373 generatingFeature PLS_INTEGER := 0;
374
375 i PLS_INTEGER;
376 j PLS_INTEGER;
377 localCount PLS_INTEGER;
378 optionCounter PLS_INTEGER;
379 trackableContext NUMBER; -- jonatara:bug7041718
380 instantiableContext NUMBER; -- jonatara:bug7041718
381 ---------------------------------------------------------------------------------------
382 PROCEDURE PACK IS
383 BEGIN
384 IF(vLogicLine IS NOT NULL)THEN
385 IF(LENGTHB(vLogicText) + LENGTHB(vLogicLine)>2000)THEN
386
387 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
388 (nStructureHeaderId, nSequenceNbr, vLogicText);
389 vLogicText := NULL;
390 nSequenceNbr := nSequenceNbr + 1;
391
392 --Commit in blocks if not disabled
393
394 IF(TwoPhaseCommit = 0)THEN
395 commit_counter := commit_counter + 1;
396 IF(commit_counter = CommitBlockSize)THEN
397 COMMIT;
398 commit_counter := 0;
399 END IF;
400 END IF;
401 END IF;
402 vLogicText := vLogicText || vLogicLine;
403 vLogicLine := NULL;
404
405 LastPacked := PACKING_GENERIC;
406
407 END IF;
408 END PACK;
409 ---------------------------------------------------------------------------------------
410 PROCEDURE PACK_EFFECTIVITY IS
411 BEGIN
412 IF(vLogicLine IS NOT NULL)THEN
413 IF(LENGTHB(vLogicText) + LENGTHB(vLogicLine)>2000)THEN
414
415 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
416 (nStructureHeaderId, nSequenceNbr, vLogicText);
417 vLogicText := NULL;
418 nSequenceNbr := nSequenceNbr + 1;
419
420 --Commit in blocks if not disabled
421
422 IF(TwoPhaseCommit = 0)THEN
423 commit_counter := commit_counter + 1;
424 IF(commit_counter = CommitBlockSize)THEN
425 COMMIT;
426 commit_counter := 0;
427 END IF;
428 END IF;
429 END IF;
430
431 IF(LastPacked = PACKING_EFFECTIVITY AND CurrentlyPacking = LastPacked)THEN
432
433 --We are inserting one effectivity statement after another. Replace the last
434 --one with the current one.
435
436 vLogicText := SUBSTR(vLogicText, 1, INSTR(vLogicText, 'EFF', -1, 1) - 1) || vLogicLine;
437
438 ELSE
439 vLogicText := vLogicText || vLogicLine;
440 END IF;
441
442 vLogicLine := NULL;
443 LastPacked := CurrentlyPacking;
444
445 END IF;
446 END PACK_EFFECTIVITY;
447 ---------------------------------------------------------------------------------------
448 PROCEDURE GENERATE_EFFECTIVITY_LOGIC(inCurrentEffFrom IN DATE,
449 inCurrentEffUntil IN DATE,
450 inCurrentUsageMask IN VARCHAR2) IS
451 BEGIN
452 IF((inCurrentEffFrom <> PrevEffFrom) OR (inCurrentEffUntil <> PrevEffUntil) OR
453 (inCurrentUsageMask <> PrevUsageMask))THEN
454
455 vLogicLine := LTRIM(inCurrentUsageMask, '0');
456 IF(vLogicLine IS NOT NULL) THEN
457 vLogicLine := EffUsagePrefix || vLogicLine;
458 END IF;
459
460 IF(inCurrentEffFrom = EpochBeginDate)THEN
461 CurrentFromDate := NULL;
462 ELSE
463 CurrentFromDate := TO_CHAR(inCurrentEffFrom, EffDateFormat);
464 END IF;
465
466 IF(inCurrentEffUntil = EpochEndDate)THEN
467 CurrentUntilDate := NULL;
468 ELSE
469 CurrentUntilDate := TO_CHAR(inCurrentEffUntil, EffDateFormat);
470 END IF;
471
472 vLogicLine := 'EFF ' || CurrentFromDate || ', ' || CurrentUntilDate || ', ' || vLogicLine || NewLine;
473
474 CurrentlyPacking := PACKING_EFFECTIVITY;
475 PACK_EFFECTIVITY;
476
477 PrevEffFrom := inCurrentEffFrom;
478 PrevEffUntil := inCurrentEffUntil;
479 PrevUsageMask := inCurrentUsageMask;
480 END IF;
481 END;
482 ---------------------------------------------------------------------------------------
483 --This procedure is used for marking BOM items that are ancestors of a trackable BOM
484 --item. Such items cannot have default quantity greater than 1, and cannot be on the
485 --RHS of a numeric rule.
486 --The procedure can be called only for a BOM Option Class or Standard or a reference,
487 --so parent always exists.
488
489 PROCEDURE PROPAGATE_TRACKABLE_ANCESTOR IS
490
491 auxIndex NUMBER := glIndexByPsNodeId(ntParentId(i)); --kdande; Bug 6881902; 11-Mar-2008
492 BEGIN
493 WHILE((NOT trackableAncestor.EXISTS(glPsNodeId(auxIndex))) AND
494 glPsNodeType(auxIndex) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))LOOP
495
496 IF(glInitialValue(auxIndex) > 1)THEN
497
498 nParam := auxIndex;
499 RAISE CZ_S_INCORRECT_QUANTITY;
500 END IF;
501
502 trackableAncestor(glPsNodeId(auxIndex)) := 1;
503 EXIT WHEN glParentId(auxIndex) IS NULL;
504
505 auxIndex := glIndexByPsNodeId(glParentId(auxIndex));
506 END LOOP;
507 END;
508 ---------------------------------------------------------------------------------------
509 FUNCTION IS_NODE_LOGICAL(j IN PLS_INTEGER) RETURN BOOLEAN IS
510 l_node_type NUMBER := ntPsNodeType(j);
511 BEGIN
512 RETURN
513 l_node_type <> PS_NODE_TYPE_TOTAL AND l_node_type <> PS_NODE_TYPE_RESOURCE AND
514 (l_node_type <> PS_NODE_TYPE_FEATURE OR
515 ntFeatureType(j) IN (PS_NODE_FEATURE_TYPE_BOOLEAN, PS_NODE_FEATURE_TYPE_OPTION) OR
516 (ntFeatureType(j) = PS_NODE_FEATURE_TYPE_INTEGER AND
517 ntMinimum(j) IS NOT NULL AND ntMinimum(j) >= 0));
518 END;
519 ---------------------------------------------------------------------------------------
520 PROCEDURE GENERATE_ACCUMULATOR(j IN PLS_INTEGER) IS
521 BEGIN
522
523 --Check if we need to create an accumulator for this node. Note that accumulator must be
524 --always effective. Part of the fix for the bug #2857955.
525
526 IF(ntAccumulator(j) IS NOT NULL AND ntAccumulator(j) <> FLAG_NO_ACCUMULATOR)THEN
527
528 GENERATE_EFFECTIVITY_LOGIC(EpochBeginDate, EpochEndDate, AnyUsageMask);
529 vLogicName := 'P_' || TO_CHAR(ntPersistentId(j));
530
531 IF((NOT v_HeaderByAccId.EXISTS(ntPsNodeId(j))) AND
532 TO_NUMBER(UTL_RAW.BIT_AND(ntAccumulator(j), FLAG_ACCUMULATOR_ACC)) = TO_NUMBER(FLAG_ACCUMULATOR_ACC))THEN
533
534 vLogicLine := 'TOTAL ' || vLogicName || '_ACC' || NewLine ||
535 'INC ' || vLogicName || '_ACC' || ' ' || vLogicName ||
536 OperatorLiterals(OPERATOR_ROUND) || NewLine;
537
538 v_HeaderByAccId(ntPsNodeId(j)) := nStructureHeaderId;
539 END IF;
540
541 IF((NOT v_HeaderByNotTrueId.EXISTS(ntPsNodeId(j))) AND
542 TO_NUMBER(UTL_RAW.BIT_AND(ntAccumulator(j), FLAG_ACCUMULATOR_NT)) = TO_NUMBER(FLAG_ACCUMULATOR_NT))THEN
543
544 --Bug #5015333. Only node that has a 'logical' value can have this type of accumulator. Initially the
545 --accumulator_flag may have been set by a NOTTRUE operator. At this time the node had to have logical
546 --value, otherwise the rule would have been rejected by a verification (HAS_LOGICAL_VALUE function in
547 --GENERATE_NOTTRUE procedure). However later the rule may have been deleted, and the type of the node
548 --changed, so that the node does not have a 'logical' value anymore. As the accumulator_flag is still
549 --set, the code below will create a 'logical' relation that may crash the engine.
550
551 IF(IS_NODE_LOGICAL(j))THEN
552
553 vLogicLine := 'OBJECT ' || vLogicName || '_NT' || NewLine ||
554 'NOTTRUE ' || vLogicName || ' ' || vLogicName || '_NT' || NewLine;
555 v_HeaderByNotTrueId(ntPsNodeId(j)) := nStructureHeaderId;
556
557 ELSE
558
559 --Although it is not necessary to reset the accumulator_flag here, doing so will allow to skip this
560 --verification in the future. This should not have any effect on the currency of the model's logic.
561
562 UPDATE cz_ps_nodes SET
563 accumulator_flag = TO_CHAR(TO_NUMBER(UTL_RAW.BIT_AND(ntAccumulator(j), FLAG_ACCUMULATOR_ACC)))
564 WHERE ps_node_id = ntPsNodeId(j);
565 END IF;
566 END IF;
567
568 PACK;
569 END IF;
570 END;
571 ---------------------------------------------------------------------------------------
572 PROCEDURE GENERATE_RULES IS
573
574 TYPE iteratorNode IS RECORD (node_type NUMBER,
575 node_id NUMBER,
576 node_value VARCHAR2(4000),
577 node_obj VARCHAR2(4000),
578 node_id_ex NUMBER);
579 TYPE tIteratorArray IS TABLE OF iteratorNode INDEX BY BINARY_INTEGER;
580
581 --The cursor returns all the rules assigned in this project (model).
582
583 CURSOR c_rules IS
584 SELECT rule_id, rule_type, antecedent_id, consequent_id, name, reason_id,
585 expr_rule_type, rule_folder_id, component_id, model_ref_expl_id,
586 effective_from, effective_until, effective_usage_mask, effectivity_set_id,
587 unsatisfied_msg_id, unsatisfied_msg_source, presentation_flag, class_name
588 FROM cz_rules
589 WHERE devl_project_id = inComponentId
590 AND deleted_flag = FLAG_NOT_DELETED
591 AND disabled_flag = FLAG_NOT_DISABLED;
592
593 v_tExplNodeId tExplNodeId;
594 v_tExprType tExprType;
595 v_tExprSubtype tExprSubtype;
596 v_tExprId tExprId;
597 v_tExprParentId tExprParentId;
598 v_tExprTemplateId tExprTemplateId;
599 v_tExprParamIndex tExprParamIndex;
600 v_tExprArgumentName tExprArgumentName;
601 v_tExprDataType tExprDataType;
602 v_tExpressId tExpressId;
603 v_tExprPsNodeId tExplNodeId;
604 v_tRealPsNodeId tExplNodeId;
605 v_tExprDataValue tExprDataValue;
606 v_tExprPropertyId tExprPropertyId;
607 v_tConsequentFlag tConsequentFlag;
608 v_tFeatureType tDesFeatureType;
609 v_tExprDataNumValue tExprDataNumValue;
610 v_tExprArgSignature tExprArgSignature;
611 v_tExprParSignature tExprParSignature;
612 v_LoadConditionId tExplNodeId;
613 v_ExplByPsNodeId tExplNodeId_idx_vc2; --kdande; Bug 6881902; 11-Mar-2008
614
615 v_tArgumentName tArgumentName;
616 v_tArgumentIndex tArgumentIndex;
617 v_tDataType tDataType;
618
619 v_InstByLevel tIntegerArray;
620 v_IndexByExprNodeId tIntegerArray_idx_vc2;
621 v_Assignable tIntegerArray;
622 v_Participant tIntegerArray;
623 v_DistinctIndex tIntegerArray;
624 v_ParticipantIndex tIntegerArray;
625 v_RuleConnectorNet tIntegerArray;
626 v_LevelCount tIntegerArray;
627 v_LevelIndex tIntegerArray;
628 v_LevelType tIntegerArray;
629 v_MarkLoadCondition tIntegerArray;
630 v_tIsHeaderGenerated tIntegerArray;
631 v_tSequenceNbr tIntegerArray;
632 v_tLogicNetType tIntegerArray;
633
634 v_NodeLogicLevel tIntegerArray;
635 v_NodeAssignable tIntegerArray;
636 v_NodeInstantiable tIntegerArray;
637 v_NodeTrackable tIntegerArray;
638 v_IsConnectorNet tIntegerArray;
639 v_ChildrenIndex tIntegerArray;
640 v_NumberOfChildren tIntegerArray;
641 v_MaxRuleExists tIntegerArray;
642 v_ProhibitInRules tIntegerArray;
643 v_ProhibitOptional tIntegerArray;
644 v_ProhibitConnector tIntegerArray;
645 v_NodeIndexPath tIntegerArray;
646 v_NodeDownPath tStringArray;
647 v_RelativeNodePath tStringArray;
648 v_AssignedDownPath tStringArray;
649 v_NodeUpPath tStringArray;
650 v_RuleQualifiedName tStringArray;
651 v_FuncQualifiedName tStringArray;
652
653 v_LoadHeaders tHeaderId;
654 v_LoadConditions tStringArray;
655
656 h_EffFrom tDateArray;
657 h_EffUntil tDateArray;
658 h_EffUsageMask tUsageMask;
659
660 PrevRuleEffFrom tDateArray;
661 PrevRuleEffUntil tDateArray;
662 PrevRuleUsageMask tUsageMask;
663
664 nAntecedentId cz_rules.antecedent_id%TYPE;
665 nConsequentId cz_rules.consequent_id%TYPE;
666 nRuleId cz_rules.rule_id%TYPE;
667 nRuleFolderId cz_rules.rule_folder_id%TYPE;
668 nRuleType cz_rules.rule_type%TYPE;
669 RuleTemplateType cz_rules.rule_type%TYPE;
670 nRuleOperator cz_rules.expr_rule_type%TYPE;
671 nReasonId cz_rules.reason_id%TYPE;
672 nComponentId cz_rules.component_id%TYPE;
673 nModelRefExplId cz_rules.model_ref_expl_id%TYPE;
674 dEffFrom cz_rules.effective_from%TYPE;
675 dEffUntil cz_rules.effective_until%TYPE;
676 nRuleEffSetId cz_rules.effectivity_set_id%TYPE;
677 nUnsatisfiedId cz_rules.unsatisfied_msg_id%TYPE;
678 nUnsatisfiedSource cz_rules.unsatisfied_msg_source%TYPE;
679 nPresentationFlag cz_rules.presentation_flag%TYPE;
680 vRuleName cz_rules.name%TYPE;
681 vUsageMask cz_rules.effective_usage_mask%TYPE;
682 vClassName cz_rules.class_name%TYPE;
683 MaxDepthId cz_model_ref_expls.model_ref_expl_id%TYPE;
684 nAux cz_model_ref_expls.model_ref_expl_id%TYPE;
685 MaxDepthValue cz_model_ref_expls.node_depth%TYPE;
686 baseDepthValue cz_model_ref_expls.node_depth%TYPE;
687 nHeaderId cz_lce_headers.lce_header_id%TYPE;
688 nPreviousHeaderId cz_lce_headers.lce_header_id%TYPE;
689 nNewLogicFileFlag PLS_INTEGER := 0;
690 nRuleAssignedLevel PLS_INTEGER;
691 MaxDepthIndex PLS_INTEGER;
692 logicNetType PLS_INTEGER;
693 expressionSize PLS_INTEGER;
694 expressionStart PLS_INTEGER;
695 expressionEnd PLS_INTEGER;
696 numericLHS PLS_INTEGER;
697 generateCompare PLS_INTEGER;
698 generateCollect PLS_INTEGER;
699
700 ConnectorIndex PLS_INTEGER;
701 InstantiableIndex PLS_INTEGER;
702 OptionalIndex PLS_INTEGER;
703 AssignableIndex PLS_INTEGER;
704 TrackableIndex PLS_INTEGER;
705
706 jAntecedentRoot PLS_INTEGER;
707 jConsequentRoot PLS_INTEGER;
708 jAntecedentRootCount PLS_INTEGER;
709 jConsequentRootCount PLS_INTEGER;
710 ListType PLS_INTEGER;
711 nLocalDefaults PLS_INTEGER := 0;
712 nLocalExprId PLS_INTEGER := 1000;
713
714 nCounter PLS_INTEGER;
715 distinctCount PLS_INTEGER;
716 participantCount PLS_INTEGER;
717 localFeatureType PLS_INTEGER;
718 localMinimum PLS_INTEGER;
719 auxIndex NUMBER; --kdande; Bug 6881902; 11-Mar-2008
720 auxCount NUMBER; --kdande; Bug 6881902; 11-Mar-2008
721 localString VARCHAR2(32000);
722 pathString VARCHAR2(32000);
723 baseString VARCHAR2(32000);
724 localNodeId NUMBER;
725 localRunId NUMBER;
726
727 generateRound PLS_INTEGER;
728 optimizeChain PLS_INTEGER;
729 optimizeContribute PLS_INTEGER;
730 optimizeTarget VARCHAR2(4000);
731 t_prefix VARCHAR2(128);
732
733 returnListType PLS_INTEGER;
734 returnStringArray tStringArray;
735
736 parameterScope tIteratorArray;
737 parameterName tStringArray;
738
739 --This type is used when it is necessary to hash a table name by a text key.
740
741 TYPE temp_table_hash_type IS TABLE OF VARCHAR2(30) INDEX BY VARCHAR2(4000);
742 temp_table_hash temp_table_hash_type;
743 temp_cmpt_table_hash temp_table_hash_type;
744
745 --Some of the variables are level specific for embedded FORALL, so we need to know the
746 --the current level. One example is the table hash key below.
747 --COMPATIBLE currently cannot be embedded, so the variable will never be greater than 1.
748
749 forallLevel PLS_INTEGER := 0;
750 compatLevel PLS_INTEGER := 0;
751
752 --This key is used to identify a temporary table constructed for an iterator and hash its
753 --name in temp_table_hash or temp_cmpt_table_hash.
754 --The format of this key is:
755 --<ps_node_id>-<model_ref_expl_id>-<property_id-1>-...-<property_id_N>
756
757 --We need tables of keys because of the possibility of embedded FORALL - on every level
758 --the level specific key should be considered.
759 --Although currently FORALL cannot be embedded into COMPATIBLE, this may change in the
760 --future, therefore it is better to have separate keys.
761
762 temp_table_hash_key tStringArray;
763 temp_cmpt_hash_key tStringArray;
764
765 --This is a universal array accumulating all the temp tables we need to delete across
766 --all FORALL(s) and COMPATIBLE(s).
767
768 temp_tables tStringArray;
769
770 --For logic and comparison rules having an unsatisified message (unsatisfied_msg_source <> 0)
771 --this string will be populated with unsatisfied_msg_id, and used as a part of GS syntax when
772 --the relation has more then one operand on either side. For all the other types of rules the
773 --string will be null.
774
775 sUnsatisfiedId VARCHAR2(4000);
776 ---------------------------------------------------------------------------------------
777 FUNCTION GET_PROPERTY_VALUE(p_node_id IN cz_ps_nodes.ps_node_id%TYPE,
778 p_property_id IN cz_properties.property_id%TYPE,
779 p_item_id IN cz_item_masters.item_id%TYPE,
780 x_data_type IN OUT NOCOPY cz_properties.data_type%TYPE)
781 RETURN VARCHAR2 IS
782 l_def_value cz_properties.def_value%TYPE;
783 l_tab tStringArray;
784 BEGIN
785
786 SELECT NVL(TO_CHAR(def_num_value), def_value), data_type INTO l_def_value, x_data_type
787 FROM cz_properties
788 WHERE property_id = p_property_id
789 AND deleted_flag = FLAG_NOT_DELETED;
790
791 SELECT NVL(TO_CHAR(data_num_value), data_value) BULK COLLECT INTO l_tab
792 FROM cz_ps_prop_vals
793 WHERE ps_node_id = p_node_id
794 AND property_id = p_property_id
795 AND deleted_flag = FLAG_NOT_DELETED;
796
797 IF(l_tab.COUNT = 0 AND p_item_id IS NOT NULL)THEN
798
799 SELECT NVL(TO_CHAR(property_num_value), property_value) BULK COLLECT INTO l_tab
800 FROM cz_item_property_values
801 WHERE property_id = p_property_id
802 AND item_id = p_item_id
803 AND deleted_flag = FLAG_NOT_DELETED;
804
805 IF(l_tab.COUNT = 0)THEN
806
807 SELECT NULL BULK COLLECT INTO l_tab
808 FROM cz_item_type_properties t, cz_item_masters m
809 WHERE m.item_id = p_item_id
810 AND m.deleted_flag = FLAG_NOT_DELETED
811 AND t.deleted_flag = FLAG_NOT_DELETED
812 AND t.property_id = p_property_id
813 AND t.item_type_id = m.item_type_id;
814 END IF;
815 END IF;
816
817 IF(l_tab.EXISTS(1))THEN
818
819 IF(x_data_type = DATATYPE_TRANSLATABLE_PROP)THEN
820
821 SELECT localized_str INTO l_tab(1) FROM cz_localized_texts
822 WHERE intl_text_id = l_tab(1) AND language = USERENV('LANG');
823
824 IF(l_tab(1) IS NULL)THEN
825
826 SELECT localized_str INTO l_tab(1) FROM cz_localized_texts
827 WHERE intl_text_id = l_def_value AND language = USERENV('LANG');
828 END IF;
829 END IF;
830
831 RETURN NVL(l_tab(1), l_def_value);
832 END IF;
833
834 x_data_type := NULL;
835 RETURN NULL;
836
837 EXCEPTION
838 WHEN NO_DATA_FOUND THEN
839 x_data_type := NULL;
840 RETURN NULL;
841 END;
842 ---------------------------------------------------------------------------------------
843 --The local procedure is required because the sequence numbers must be different
844 --Still works with global buffers and commit parameters
845
846 PROCEDURE PACK IS
847 BEGIN
848 IF(vLogicLine IS NOT NULL)THEN
849 IF(LENGTHB(vLogicText) + LENGTHB(vLogicLine)>2000)THEN
850
851 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
852 (nHeaderId, v_tSequenceNbr(nHeaderId), vLogicText);
853 vLogicText := NULL;
854 v_tSequenceNbr(nHeaderId) := v_tSequenceNbr(nHeaderId) + 1;
855
856 --Commit in blocks if not disabled
857
858 IF(TwoPhaseCommit = 0)THEN
859 commit_counter := commit_counter + 1;
860 IF(commit_counter = CommitBlockSize)THEN
861 COMMIT;
862 commit_counter := 0;
863 END IF;
864 END IF;
865 END IF;
866 vLogicText := vLogicText || vLogicLine;
867 vLogicLine := NULL;
868 END IF;
869 END PACK;
870 ---------------------------------------------------------------------------------------
871 --This function returns fully qualified rule name given rule_folder_id of a rule
872 --and puts generated names into a hash table for reuse.
873
874 FUNCTION RULE_NAME RETURN VARCHAR2 IS
875 vQualified VARCHAR2(4000) := '.';
876 nRuleName PLS_INTEGER;
877 BEGIN
878 IF(nRuleFolderId IS NULL OR nRuleFolderId = -1)THEN RETURN vRuleName; END IF;
879 IF(v_RuleQualifiedName.EXISTS(nRuleFolderId))THEN RETURN v_RuleQualifiedName(nRuleFolderId) || vRuleName; END IF;
880 nRuleName := LENGTHB(vRuleName);
881 FOR folder IN (SELECT name FROM cz_rule_folders
882 WHERE deleted_flag = FLAG_NOT_DELETED
883 AND parent_rule_folder_id IS NOT NULL
884 START WITH rule_folder_id = nRuleFolderId
885 AND object_type = 'RFL'
886 CONNECT BY PRIOR parent_rule_folder_id = rule_folder_id
887 AND object_type = 'RFL')LOOP
888 IF(LENGTHB(folder.name) + LENGTHB(vQualified) + 1 < 2000 - nRuleName)THEN
889 vQualified := '.' || folder.name || vQualified;
890 ELSE
891 EXIT;
892 END IF;
893 END LOOP;
894 v_RuleQualifiedName(nRuleFolderId) := vQualified;
895 RETURN vQualified || vRuleName;
896 END;
897 ---------------------------------------------------------------------------------------
898 --This function returns fully qualified name of a functional companion given
899 --rule_folder_id.
900
901 FUNCTION COMPANION_NAME(inCompanionName IN VARCHAR2, inFolderId IN NUMBER) RETURN VARCHAR2 IS
902 vQualified VARCHAR2(4000) := '.';
903 nameLen PLS_INTEGER;
904 BEGIN
905 IF(inFolderId IS NULL OR inFolderId = -1)THEN RETURN inCompanionName; END IF;
906 IF(v_FuncQualifiedName.EXISTS(inFolderId))THEN RETURN v_FuncQualifiedName(inFolderId) || inCompanionName; END IF;
907 nameLen := LENGTHB(inCompanionName);
908 FOR folder IN (SELECT name FROM cz_rule_folders
909 WHERE deleted_flag = FLAG_NOT_DELETED
910 AND parent_rule_folder_id IS NOT NULL
911 START WITH rule_folder_id = inFolderId
912 CONNECT BY PRIOR parent_rule_folder_id = rule_folder_id)LOOP
913 IF(LENGTHB(folder.name) + LENGTHB(vQualified) + 1 < 2000 - nameLen)THEN
914 vQualified := '.' || folder.name || vQualified;
915 ELSE
916 EXIT;
917 END IF;
918 END LOOP;
919 v_FuncQualifiedName(inFolderId) := vQualified;
920 RETURN vQualified || inCompanionName;
921 END;
922 ---------------------------------------------------------------------------------------
923 --The ps_node_id value is fixed in the memory for references to BOM. This function can
924 --be called when the original value (ps_node_id of the reference node) is required.
925
926 FUNCTION REAL_PS_NODE_ID(j IN PLS_INTEGER) RETURN NUMBER IS
927 BEGIN
928 IF(v_tRealPsNodeId.EXISTS(j))THEN RETURN v_tRealPsNodeId(j); ELSE RETURN v_tExprPsNodeId(j); END IF;
929 END;
930 ---------------------------------------------------------------------------------------
931 FUNCTION SIGNATURE_DATA_TYPE(p_signature_id IN NUMBER) RETURN PLS_INTEGER IS
932 v_data_type PLS_INTEGER;
933 BEGIN
934 IF(h_SignatureDataType.EXISTS(p_signature_id))THEN RETURN h_SignatureDataType(p_signature_id); END IF;
935
936 BEGIN
937 SELECT data_type INTO v_data_type FROM cz_signatures
938 WHERE deleted_flag = FLAG_NOT_DELETED
939 AND signature_id = p_signature_id;
940
941 h_SignatureDataType(p_signature_id) := v_data_type;
942 RETURN v_data_type;
943 EXCEPTION
944 WHEN OTHERS THEN
945 RAISE CZ_R_NO_SIGNATURE_ID;
946 END;
947 END;
948 ---------------------------------------------------------------------------------------
949 FUNCTION COMPATIBLE_DATA_TYPES(p_object_type IN PLS_INTEGER, p_subject_type PLS_INTEGER) RETURN BOOLEAN IS
950 v_null PLS_INTEGER;
951 BEGIN
952 SELECT NULL INTO v_null FROM cz_conversion_rels_v
953 WHERE object_type = p_object_type AND subject_type = p_subject_type;
954 RETURN TRUE;
955 EXCEPTION
956 WHEN NO_DATA_FOUND THEN
957 RETURN FALSE;
958 WHEN TOO_MANY_ROWS THEN
959 RETURN TRUE;
960 WHEN OTHERS THEN
961 RETURN FALSE;
962 END;
963 ---------------------------------------------------------------------------------------
964 FUNCTION GET_ARGUMENT_INFO(p_param_index IN NUMBER,
965 p_signature_id IN NUMBER,
966 x_mutable IN OUT NOCOPY VARCHAR2,
967 x_collection IN OUT NOCOPY VARCHAR2)
968 RETURN NUMBER IS
969 v_data_type cz_signature_arguments.data_type%TYPE;
970 BEGIN
971 SELECT data_type, mutable_flag, collection_flag INTO v_data_type, x_mutable, x_collection
972 FROM cz_signature_arguments
973 WHERE deleted_flag = FLAG_NOT_DELETED
974 AND argument_signature_id = p_signature_id
975 AND argument_index = p_param_index;
976 RETURN v_data_type;
977 EXCEPTION
978 WHEN OTHERS THEN
979 RETURN DATA_TYPE_VOID;
980 END;
981 ---------------------------------------------------------------------------------------
982 FUNCTION APPLICABLE_SYS_PROP(j IN PLS_INTEGER, p_ps_node_id IN NUMBER, p_rule_id IN NUMBER) RETURN BOOLEAN IS
983 v_null PLS_INTEGER;
984 v_ps_node_id NUMBER;
985 v_data_type cz_signature_arguments.data_type%TYPE;
986 v_mutable cz_signature_arguments.mutable_flag%TYPE;
987 v_collection cz_signature_arguments.collection_flag%TYPE;
988 BEGIN
989
990 --Some of the upgraded rules may not have param_index and param_signature_id populated. However, upgraded
991 --rules are not real statement rules, so they are not supposed to have any user error in them and in this
992 --case the verification is not required.
993
994 IF(v_tExprParamIndex(j) IS NULL OR v_tExprParSignature(j) IS NULL)THEN RETURN TRUE; END IF;
995
996 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;
997 v_data_type := GET_ARGUMENT_INFO(v_tExprParamIndex(j), v_tExprParSignature(j), v_mutable, v_collection);
998
999 SELECT NULL INTO v_null
1000 FROM cz_rul_typedpsn_v psn,
1001 cz_conversion_rels_v cnv,
1002 cz_system_property_rels_v rel,
1003 cz_system_properties_v sys,
1004 cz_conversion_rels_v cnv2
1005 WHERE psn.detailed_type_id = cnv.object_type
1006 AND cnv.subject_type = rel.subject_type
1007 AND rel.object_type = sys.rule_id
1008 AND rel.rel_type_code = 'SYS'
1009 AND sys.data_type = cnv2.object_type
1010 AND psn.ps_node_id = v_ps_node_id
1011 AND sys.rule_id = p_rule_id
1012 AND sys.mutable_flag >= v_mutable
1013 AND sys.collection_flag <= v_collection
1014 AND cnv2.subject_type = v_data_type;
1015
1016 RETURN TRUE;
1017 EXCEPTION
1018 WHEN NO_DATA_FOUND THEN
1019 RETURN FALSE;
1020 WHEN TOO_MANY_ROWS THEN
1021 RETURN TRUE;
1022 WHEN OTHERS THEN
1023 RETURN FALSE;
1024 END;
1025 ---------------------------------------------------------------------------------------
1026 FUNCTION APPLICABLE_SYS_PROP(j IN PLS_INTEGER, p_ps_node_id IN NUMBER, p_rule_name IN VARCHAR2) RETURN BOOLEAN IS
1027 v_null PLS_INTEGER;
1028 v_ps_node_id NUMBER;
1029 v_data_type cz_signature_arguments.data_type%TYPE;
1030 v_mutable cz_signature_arguments.mutable_flag%TYPE;
1031 v_collection cz_signature_arguments.collection_flag%TYPE;
1032 BEGIN
1033
1034 --Some of the upgraded rules may not have param_index and param_signature_id populated. However, upgraded
1035 --rules are not real statement rules, so they are not supposed to have any user error in them and in this
1036 --case the verification is not required.
1037
1038 IF(v_tExprParamIndex(j) IS NULL OR v_tExprParSignature(j) IS NULL)THEN RETURN TRUE; END IF;
1039
1040 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;
1041 v_data_type := GET_ARGUMENT_INFO(v_tExprParamIndex(j), v_tExprParSignature(j), v_mutable, v_collection);
1042
1043 SELECT NULL INTO v_null
1044 FROM cz_rul_typedpsn_v psn,
1045 cz_conversion_rels_v cnv,
1046 cz_system_property_rels_v rel,
1047 cz_system_properties_v sys,
1048 cz_conversion_rels_v cnv2
1049 WHERE psn.detailed_type_id = cnv.object_type
1050 AND cnv.subject_type = rel.subject_type
1051 AND rel.object_type = sys.rule_id
1052 AND rel.rel_type_code = 'SYS'
1053 AND sys.data_type = cnv2.object_type
1054 AND psn.ps_node_id = v_ps_node_id
1055 AND UPPER(sys.name) = p_rule_name
1056 AND sys.mutable_flag >= v_mutable
1057 AND sys.collection_flag <= v_collection
1058 AND cnv2.subject_type = v_data_type;
1059
1060 RETURN TRUE;
1061 EXCEPTION
1062 WHEN NO_DATA_FOUND THEN
1063 RETURN FALSE;
1064 WHEN TOO_MANY_ROWS THEN
1065 RETURN TRUE;
1066 WHEN OTHERS THEN
1067 RETURN FALSE;
1068 END;
1069 ---------------------------------------------------------------------------------------
1070 --Splits the CHR(7)-separated path into an array of node names.
1071
1072 FUNCTION SPLIT_PATH(p_path IN VARCHAR2) RETURN tStringArray IS
1073
1074 l_substr VARCHAR2(32000) := p_path;
1075 l_index PLS_INTEGER;
1076 l_return_tbl tStringArray;
1077 BEGIN
1078
1079 IF(p_path IS NULL)THEN RETURN l_return_tbl; END IF;
1080 LOOP
1081
1082 l_index := INSTR(l_substr, FND_GLOBAL.LOCAL_CHR(7));
1083
1084 IF(l_index > 0)THEN
1085
1086 l_return_tbl(l_return_tbl.COUNT + 1) := SUBSTR(l_substr, 1, l_index - 1);
1087 l_substr := SUBSTR(l_substr, l_index + 1);
1088 ELSE
1089
1090 l_return_tbl(l_return_tbl.COUNT + 1) := l_substr;
1091 EXIT;
1092 END IF;
1093 END LOOP;
1094
1095 RETURN l_return_tbl;
1096 END;
1097 ---------------------------------------------------------------------------------------
1098 PROCEDURE RESOLVE_NODE(p_node_tbl IN tStringArray,
1099 p_parent_node_id IN NUMBER,
1100 p_parent_expl_id IN NUMBER,
1101 x_child_node_id IN OUT NOCOPY NUMBER,
1102 x_child_expl_id IN OUT NOCOPY NUMBER) IS
1103
1104 l_eff_from DATE := EpochBeginDate;
1105 l_eff_until DATE := EpochEndDate;
1106 l_index PLS_INTEGER;
1107 l_parent_id NUMBER;
1108
1109 l_return_node_id_tbl tNumberArray;
1110 l_return_expl_id_tbl tNumberArray;
1111
1112 FUNCTION REPORT_PATH RETURN VARCHAR2 IS
1113
1114 l_return VARCHAR2(32000) := NULL;
1115 BEGIN
1116
1117 FOR i IN 1..p_node_tbl.COUNT LOOP
1118
1119 IF(l_return IS NOT NULL)THEN l_return := l_return || '.'; END IF;
1120 l_return := l_return || p_node_tbl(i);
1121 END LOOP;
1122 RETURN l_return;
1123 END;
1124
1125 PROCEDURE RESOLVE_CHILDREN(p_index IN PLS_INTEGER,
1126 p_node_id IN NUMBER,
1127 p_expl_id IN NUMBER,
1128 p_eff_from IN DATE,
1129 p_eff_until IN DATE) IS
1130
1131 t_eff_from_tbl tDateArray;
1132 t_eff_until_tbl tDateArray;
1133 t_node_id_tbl tNumberArray;
1134 t_expl_id_tbl tNumberArray;
1135 l_eff_from_tbl tDateArray;
1136 l_eff_until_tbl tDateArray;
1137 l_node_id_tbl tNumberArray;
1138 l_expl_id_tbl tNumberArray;
1139
1140 l_counter PLS_INTEGER := 0;
1141 l_index PLS_INTEGER;
1142 BEGIN
1143
1144 SELECT ps_node_id, model_ref_expl_id, effective_from, effective_until
1145 BULK COLLECT INTO l_node_id_tbl, l_expl_id_tbl, l_eff_from_tbl, l_eff_until_tbl
1146 FROM cz_explmodel_nodes_v
1147 WHERE model_id = inComponentId
1148 AND parent_psnode_expl_id = p_expl_id
1149 AND effective_parent_id = p_node_id
1150 AND suppress_flag = '0'
1151 AND name = p_node_tbl(p_index);
1152
1153 FOR i IN 1..l_node_id_tbl.COUNT LOOP
1154
1155 IF(p_eff_from > l_eff_from_tbl(i))THEN l_eff_from_tbl(i) := p_eff_from; END IF;
1156 IF(p_eff_until < l_eff_until_tbl(i))THEN l_eff_until_tbl(i) := p_eff_until; END IF;
1157
1158 IF(l_eff_from_tbl(i) <= l_eff_until_tbl(i))THEN
1159
1160 l_counter := l_counter + 1;
1161
1162 t_eff_from_tbl(l_counter) := l_eff_from_tbl(i);
1163 t_eff_until_tbl(l_counter) := l_eff_until_tbl(i);
1164 t_node_id_tbl(l_counter) := l_node_id_tbl(i);
1165 t_expl_id_tbl(l_counter) := l_expl_id_tbl(i);
1166 END IF;
1167 END LOOP;
1168
1169 FOR i IN 1..t_node_id_tbl.COUNT LOOP
1170
1171 IF(p_index = p_node_tbl.COUNT)THEN
1172
1173 l_index := l_return_node_id_tbl.COUNT + 1;
1174
1175 l_return_node_id_tbl(l_index) := t_node_id_tbl(i);
1176 l_return_expl_id_tbl(l_index) := t_expl_id_tbl(i);
1177 ELSE
1178
1179 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));
1180 END IF;
1181 END LOOP;
1182 END;
1183 BEGIN
1184
1185 --Propagate effectivity from all the bom references down from the root model.
1186
1187 FOR i IN 1..globalLevel LOOP
1188
1189 --We need to stop on the model, in which the rule is defined.
1190
1191 IF(globalStack(i) = inComponentId)THEN EXIT; END IF;
1192
1193 --Account only for references to bom(s).
1194
1195 IF(glPsNodeType(glIndexByPsNodeId(globalStack(i))) IN (PS_NODE_TYPE_BOM_MODEL,PS_NODE_TYPE_BOM_OPTIONCLASS,PS_NODE_TYPE_BOM_STANDARD))THEN
1196
1197 l_index := glIndexByPsNodeId(globalRef(i));
1198
1199 IF(glEffFrom(l_index) > l_eff_from)THEN l_eff_from := glEffFrom(l_index); END IF;
1200 IF(glEffUntil(l_index) < l_eff_until)THEN l_eff_until := glEffUntil(l_index); END IF;
1201 END IF;
1202 END LOOP;
1203
1204 --Adjust effectivities for the least unambiguous parent.
1205
1206 l_index := glIndexByPsNodeId(p_parent_node_id);
1207
1208 IF(glEffFrom(l_index) > l_eff_from)THEN l_eff_from := glEffFrom(l_index); END IF;
1209 IF(glEffUntil(l_index) < l_eff_until)THEN l_eff_until := glEffUntil(l_index); END IF;
1210
1211 --Finally adjust for the rule effectivity.
1212
1213 IF(dEffFrom > l_eff_from)THEN l_eff_from := dEffFrom; END IF;
1214 IF(dEffUntil < l_eff_until)THEN l_eff_until := dEffUntil; END IF;
1215
1216 --If effectivity range is empty, it will be impossible to resolve the node.
1217
1218 IF(l_eff_until < l_eff_from)THEN
1219
1220 localString := REPORT_PATH;
1221 RAISE CZ_R_INCORRECT_REFERENCE;
1222 END IF;
1223
1224 IF(p_node_tbl.COUNT = 0)THEN
1225
1226 x_child_node_id := p_parent_node_id;
1227 x_child_expl_id := p_parent_expl_id;
1228 RETURN;
1229 END IF;
1230
1231 RESOLVE_CHILDREN(1, p_parent_node_id, p_parent_expl_id, l_eff_from, l_eff_until);
1232
1233 IF(l_return_node_id_tbl.COUNT = 0)THEN
1234
1235 localString := REPORT_PATH;
1236 RAISE CZ_R_INCORRECT_REFERENCE;
1237 ELSIF(l_return_node_id_tbl.COUNT > 1)THEN
1238
1239 localString := REPORT_PATH;
1240 RAISE CZ_R_AMBIGUOUS_REFERENCE;
1241 ELSE
1242
1243 x_child_node_id := l_return_node_id_tbl(1);
1244 x_child_expl_id := l_return_expl_id_tbl(1);
1245 END IF;
1246 END;
1247 ---------------------------------------------------------------------------------------
1248 --Forward declarations block.
1249
1250 FUNCTION GENERATE_EXPRESSION(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray;
1251 FUNCTION GENERATE_REFNODE(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray;
1252 FUNCTION LOOKUP_ARGUMENT(j IN PLS_INTEGER) RETURN PLS_INTEGER;
1253 FUNCTION GENERATE_ARGUMENT(j IN PLS_INTEGER, ListType IN OUT NOCOPY PLS_INTEGER) RETURN tStringArray;
1254 ---------------------------------------------------------------------------------------
1255 FUNCTION HAS_LOGICAL_VALUE(j IN PLS_INTEGER) RETURN BOOLEAN IS
1256 NodeType PLS_INTEGER := v_tExprType(j);
1257 PsNodeType PLS_INTEGER;
1258 PsNodeIndex PLS_INTEGER;
1259 BEGIN
1260
1261 --When the validation is made from the high-level section of a logic rule, some of the participants
1262 --may still be arguments, so we need to look up the value of the argument before validating its
1263 --type. The argument in this case can be either a literal or a node (bug #3388169).
1264
1265 IF(NodeType = EXPR_ARGUMENT)THEN
1266
1267 PsNodeIndex := LOOKUP_ARGUMENT(j);
1268 IF(parameterScope(PsNodeIndex).node_id IS NULL)THEN RETURN FALSE; END IF;
1269
1270 NodeType := EXPR_PSNODE;
1271 v_tExprPsNodeId(j) := parameterScope(PsNodeIndex).node_id;
1272 END IF;
1273
1274 IF(NodeType = EXPR_NODE_TYPE_LITERAL)THEN
1275 RETURN (v_tExprDataType(j) = DATA_TYPE_BOOLEAN);
1276 ELSIF(NodeType = EXPR_PSNODE)THEN
1277 IF(v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN RETURN TRUE;
1278 ELSE
1279
1280 PsNodeIndex := glIndexByPsNodeId(v_tExprPsNodeId(j));
1281 PsNodeType := glPsNodeType(PsNodeIndex);
1282
1283 RETURN
1284 PsNodeType <> PS_NODE_TYPE_TOTAL
1285 AND
1286 PsNodeType <> PS_NODE_TYPE_RESOURCE
1287 AND
1288 (
1289 PsNodeType <> PS_NODE_TYPE_FEATURE
1290 OR
1291 glFeatureType(PsNodeIndex) IN (PS_NODE_FEATURE_TYPE_BOOLEAN, PS_NODE_FEATURE_TYPE_OPTION)
1292 OR
1293 (
1294 glFeatureType(PsNodeIndex) = PS_NODE_FEATURE_TYPE_INTEGER
1295 AND
1296 glMinimum(PsNodeIndex) IS NOT NULL
1297 AND
1298 glMinimum(PsNodeIndex) >= 0
1299 )
1300 );
1301 END IF;
1302 ELSIF(NodeType = EXPR_NODE_TYPE_OPERATOR)THEN
1303 RETURN COMPATIBLE_DATA_TYPES(SIGNATURE_DATA_TYPE(h_SignatureId(v_tExprSubtype(j))), DATA_TYPE_BOOLEAN);
1304 ELSIF(NodeType IN (EXPR_FORALL, EXPR_FORALL_DISTINCT))THEN
1305 RETURN TRUE;
1306 ELSE
1307 RETURN FALSE;
1308 END IF;
1309 END;
1310 ---------------------------------------------------------------------------------------
1311 FUNCTION HAS_OPTIONS_APPLIED(j IN PLS_INTEGER) RETURN BOOLEAN IS
1312 BEGIN
1313 RETURN (v_ChildrenIndex.EXISTS(v_tExprId(j)) AND
1314 h_SeededName.EXISTS(v_tExprSubtype(v_ChildrenIndex(v_tExprId(j)))) AND
1315 h_SeededName(v_tExprSubtype(v_ChildrenIndex(v_tExprId(j)))) = RULE_SYS_PROP_OPTIONS);
1316 END;
1317 ---------------------------------------------------------------------------------------
1318 FUNCTION GENERATE_NODE_CHILDREN(j IN PLS_INTEGER) RETURN tStringArray IS
1319 v_return tStringArray;
1320 nChild PLS_INTEGER;
1321 nCount PLS_INTEGER;
1322 oper tStringArray;
1323 ListType PLS_INTEGER;
1324 BEGIN
1325
1326 --nDebug := 7000005;
1327
1328 nCount := 1;
1329 nChild := v_ChildrenIndex(v_tExprId(j));
1330
1331 --nDebug := 7000006;
1332
1333 WHILE(v_tExprParentId(nChild) = v_tExprId(j)) LOOP
1334
1335 --nDebug := 7000007;
1336
1337 oper.DELETE;
1338 oper := GENERATE_EXPRESSION(nChild, ListType);
1339
1340 FOR i IN 1..oper.COUNT LOOP
1341
1342 v_return(nCount) := oper(i);
1343 nCount := nCount + 1;
1344
1345 END LOOP;
1346
1347 nChild := nChild + 1;
1348
1349 END LOOP;
1350
1351 --nDebug := 7000008;
1352
1353 RETURN v_return;
1354 END;
1355 ---------------------------------------------------------------------------------------
1356 FUNCTION GENERATE_NAME(j IN PLS_INTEGER, id IN NUMBER) RETURN VARCHAR2 IS --kdande; Bug 6881902; 11-Mar-2008
1357 v_return VARCHAR2(4000);
1358 counter PLS_INTEGER;
1359 val PLS_INTEGER;
1360 delimiter CHAR(1) := NULL;
1361 ExplId cz_model_ref_expls.model_ref_expl_id%TYPE := v_tExplNodeId(j);
1362 BEGIN
1363
1364 IF(NOT v_NodeUpPath.EXISTS(ExplId))THEN
1365 counter := nRuleAssignedLevel;
1366 val := v_NodeLogicLevel(ExplId);
1367 WHILE(counter > val) LOOP
1368 v_return := v_return || PATH_DELIMITER || 'parent';
1369 counter := counter - 1;
1370 END LOOP;
1371 v_NodeUpPath(ExplId) := v_return;
1372 ELSE
1373 v_return := v_NodeUpPath(ExplId);
1374 END IF;
1375
1376 IF(v_tLogicNetType(nHeaderId) = LOGIC_NET_TYPE_NETWORK AND (NOT v_IsConnectorNet.EXISTS(ExplId)))THEN
1377
1378 --If we are generating into a conditional net, we add an extra ^parent to the path, but only if
1379 --this is not a connector's net.
1380
1381 v_return := PATH_DELIMITER || 'parent' || v_return;
1382 END IF;
1383
1384 IF(v_return IS NOT NULL OR v_AssignedDownPath(ExplId) IS NOT NULL)THEN
1385 delimiter := PATH_DELIMITER;
1386 END IF;
1387
1388 v_return := v_return || v_AssignedDownPath(ExplId) || delimiter;
1389
1390 --The description below is only true if the reference participates in the rule as an
1391 --object, because if this is a rule against this reference's system property than we
1392 --still should generate the regular name. So, we need to make sure that we construct
1393 --the new name only if this reference participates in compatibility rules - the only
1394 --type of rules where it can participate as an object (an option). Bug #2567898.
1395
1396 IF(nRuleType IN (RULE_TYPE_COMPAT_RULE, RULE_TYPE_COMPAT_TABLE, RULE_TYPE_DESIGNCHART_RULE) AND
1397 glPsNodeType(glIndexByPsNodeId(id)) = PS_NODE_TYPE_REFERENCE)THEN
1398
1399 --The following comment is not exactly correct, see the above description.
1400 --The node identified by <id> is a reference. In this case we should not generate
1401 --the regular P_<id>, because such object would never exist. Instead, we generate
1402 --^N_<id>^P_<reference_id> to refer to the referenced object in the child subnet.
1403 --This fixes the base bug #2128641.
1404
1405 IF(v_return IS NULL)THEN v_return := PATH_DELIMITER; END IF;
1406 v_return := v_return || 'N_' || TO_CHAR(glPersistentId(id)) || PATH_DELIMITER ||
1407 'P_' || TO_CHAR(glReferenceId(id));
1408 ELSE
1409
1410 v_return := v_return || 'P_' || TO_CHAR(glPersistentId(id));
1411 END IF;
1412
1413 RETURN v_return;
1414 END;
1415 ---------------------------------------------------------------------------------------
1416 --Special version of GENERATE_NAME that accepts model_ref_expl_id value as a parameter
1417 --instead of extracting it from cz_expression nodes by index j.
1418
1419 FUNCTION GENERATE_NAME_EXPL(ExplId IN PLS_INTEGER, id IN NUMBER) RETURN VARCHAR2 IS --kdande; Bug 6881902; 11-Mar-2008
1420 v_return VARCHAR2(4000);
1421 counter PLS_INTEGER;
1422 val PLS_INTEGER;
1423 delimiter CHAR(1) := NULL;
1424 BEGIN
1425
1426 IF(NOT v_NodeUpPath.EXISTS(ExplId))THEN
1427 counter := nRuleAssignedLevel;
1428 val := v_NodeLogicLevel(ExplId);
1429 WHILE(counter > val) LOOP
1430 v_return := v_return || PATH_DELIMITER || 'parent';
1431 counter := counter - 1;
1432 END LOOP;
1433 v_NodeUpPath(ExplId) := v_return;
1434 ELSE
1435 v_return := v_NodeUpPath(ExplId);
1436 END IF;
1437
1438 IF(v_tLogicNetType(nHeaderId) = LOGIC_NET_TYPE_NETWORK AND (NOT v_IsConnectorNet.EXISTS(ExplId)))THEN
1439
1440 --If we are generating into a conditional net, we add an extra ^parent to the path, but only if
1441 --this is not a connector's net.
1442
1443 v_return := PATH_DELIMITER || 'parent' || v_return;
1444 END IF;
1445
1446 IF(v_return IS NOT NULL OR v_AssignedDownPath(ExplId) IS NOT NULL)THEN
1447 delimiter := PATH_DELIMITER;
1448 END IF;
1449
1450 v_return := v_return || v_AssignedDownPath(ExplId) || delimiter;
1451
1452 --The description below is only true if the reference participates in the rule as an
1453 --object, because if this is a rule against this reference's system property than we
1454 --still should generate the regular name. So, we need to make sure that we construct
1455 --the new name only if this reference participates in compatibility rules - the only
1456 --type of rules where it can participate as an object (an option). Bug #2567898.
1457
1458 IF(nRuleType IN (RULE_TYPE_COMPAT_RULE, RULE_TYPE_COMPAT_TABLE, RULE_TYPE_DESIGNCHART_RULE) AND
1459 glPsNodeType(glIndexByPsNodeId(id)) = PS_NODE_TYPE_REFERENCE)THEN
1460
1461 --The following comment is not exactly correct, see the above description.
1462 --The node identified by <id> is a reference. In this case we should not generate
1463 --the regular P_<id>, because such object would never exist. Instead, we generate
1464 --^N_<id>^P_<reference_id> to refer to the referenced object in the child subnet.
1465 --This fixes the base bug #2128641.
1466
1467 IF(v_return IS NULL)THEN v_return := PATH_DELIMITER; END IF;
1468 v_return := v_return || 'N_' || TO_CHAR(glPersistentId(id)) || PATH_DELIMITER ||
1469 'P_' || TO_CHAR(glReferenceId(id));
1470 ELSE
1471
1472 v_return := v_return || 'P_' || TO_CHAR(glPersistentId(id));
1473 END IF;
1474
1475 RETURN v_return;
1476 END;
1477 ---------------------------------------------------------------------------------------
1478 FUNCTION GENERATE_NODE(j IN PLS_INTEGER) RETURN tStringArray IS
1479 v_return tStringArray;
1480 BEGIN
1481
1482 v_return(1) := GENERATE_NAME(j, v_tExprPsNodeId(j));
1483 RETURN v_return;
1484
1485 END;
1486 ---------------------------------------------------------------------------------------
1487 FUNCTION ADJUSTED_EXPLOSION(p_parent_expl_id IN NUMBER, p_child_node_id IN NUMBER) RETURN NUMBER IS
1488 BEGIN
1489 FOR i IN 1..v_NodeId.COUNT LOOP
1490 IF(v_tParentId(i) = p_parent_expl_id AND v_tReferringId(i) = p_child_node_id)THEN
1491 RETURN v_NodeId(i);
1492 END IF;
1493 END LOOP;
1494 END;
1495 ---------------------------------------------------------------------------------------
1496 FUNCTION EXPAND_NODE(j IN PLS_INTEGER) RETURN tIntegerArray IS
1497 v_result tIntegerArray;
1498 nCount PLS_INTEGER;
1499 v_ps_node_id NUMBER; --kdande; Bug 6881902; 11-Mar-2008
1500 v_node_type PLS_INTEGER;
1501 v_index PLS_INTEGER;
1502 v_start_index PLS_INTEGER;
1503 v_end_index PLS_INTEGER;
1504 BEGIN
1505
1506 IF(v_tExprType(j) = EXPR_OPERATOR)THEN
1507
1508 --The function is called on an operator node. We assume that this is OptionsOf, and so it has one
1509 --operand which represents a structure node. This structure node has its explosion populated in
1510 --cz_expression_nodes table. It is often convenient to associate this explosion also with the
1511 --operator itself. This is a fix for the bug #2232741.
1512
1513 v_ps_node_id := v_tExprPsNodeId(v_ChildrenIndex(v_tExprId(j)));
1514 v_tExplNodeId(j) := v_tExplNodeId(v_ChildrenIndex(v_tExprId(j)));
1515
1516 ELSIF(v_tExprType(j) = EXPR_PSNODE AND v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
1517
1518 v_ps_node_id := v_tExprPsNodeId(j);
1519 ELSE
1520
1521 --Left for backward compatibility.
1522
1523 v_result(1) := v_tExprPsNodeId(j);
1524 RETURN v_result;
1525 END IF;
1526
1527 v_index := glIndexByPsNodeId(v_ps_node_id);
1528 v_node_type := glPsNodeType(v_index);
1529 v_start_index := v_index + 1;
1530
1531 IF(NOT glLastChildIndex.EXISTS(v_ps_node_id))THEN
1532
1533 localString := glName(v_index);
1534 RAISE CZ_E_NO_EXPECTED_CHILDREN;
1535 END IF;
1536
1537 v_end_index := glLastChildIndex(v_ps_node_id);
1538 nCount := 1;
1539
1540 --If the function is called on a feature, we return options. If the function is called on a
1541 --BOM node, we return BOM children.
1542
1543 IF(v_node_type = PS_NODE_TYPE_FEATURE)THEN
1544
1545 FOR i IN v_start_index..v_end_index LOOP
1546
1547 v_result(nCount) := glPsNodeId(i);
1548 v_ExplByPsNodeId(glPsNodeId(i)) := v_tExplNodeId(j);
1549 nCount := nCount + 1;
1550 END LOOP;
1551 ELSIF(v_node_type IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
1552
1553 FOR i IN v_start_index..v_end_index LOOP
1554
1555 IF((glPsNodeType(i) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD) OR
1556 (glPsNodeType(i) = PS_NODE_TYPE_REFERENCE AND
1557 glPsNodeType(glIndexByPsNodeId(glReferenceId(glPsNodeId(i)))) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD)))
1558 AND glParentId(i) = v_ps_node_id)THEN
1559
1560 IF(glPsNodeType(i) = PS_NODE_TYPE_REFERENCE)THEN
1561 v_result(nCount) := glReferenceId(glPsNodeId(i));
1562 v_ExplByPsNodeId(glReferenceId(glPsNodeId(i))) := ADJUSTED_EXPLOSION(v_tExplNodeId(j), glPsNodeId(i));
1563 ELSE
1564 v_result(nCount) := glPsNodeId(i);
1565 v_ExplByPsNodeId(glPsNodeId(i)) := v_tExplNodeId(j);
1566 END IF;
1567 nCount := nCount + 1;
1568 END IF;
1569 END LOOP;
1570 END IF;
1571 RETURN v_result;
1572 END;
1573 ---------------------------------------------------------------------------------------
1574 FUNCTION GENERATE_CHILDRENOF(p_expl_id IN PLS_INTEGER, p_ps_node_id IN NUMBER) RETURN tStringArray IS --kdande; Bug 6881902; 11-Mar-2008
1575 v_return tStringArray;
1576 nCount PLS_INTEGER;
1577 v_node_type PLS_INTEGER;
1578 v_index PLS_INTEGER;
1579 v_start_index PLS_INTEGER;
1580 v_end_index PLS_INTEGER;
1581 BEGIN
1582
1583 nDebug := 7004050;
1584
1585 --This function does basically the same as the previous one. The difference is that it can be used
1586 --only for system property, it is called on the system property node, taking the ps_node_id of the
1587 --parent as a parameter, and it returns generated names.
1588
1589 v_index := glIndexByPsNodeId(p_ps_node_id);
1590 v_node_type := glPsNodeType(v_index);
1591 v_start_index := v_index + 1;
1592
1593 IF(NOT glLastChildIndex.EXISTS(p_ps_node_id))THEN
1594
1595 localString := glName(v_index);
1596 RAISE CZ_E_NO_EXPECTED_CHILDREN;
1597 END IF;
1598
1599 v_end_index := glLastChildIndex(p_ps_node_id);
1600 nCount := 1;
1601
1602 --If the function is called on a feature, we return options. If the function is called on a
1603 --BOM node, we return BOM children.
1604
1605 IF(v_node_type = PS_NODE_TYPE_FEATURE)THEN
1606
1607 FOR i IN v_start_index..v_end_index LOOP
1608
1609 v_return(nCount) := GENERATE_NAME_EXPL(p_expl_id, glPsNodeId(i));
1610 nCount := nCount + 1;
1611 END LOOP;
1612
1613 ELSIF(v_node_type IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
1614
1615 FOR i IN v_start_index..v_end_index LOOP
1616 IF((glPsNodeType(i) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD) OR
1617 (glPsNodeType(i) = PS_NODE_TYPE_REFERENCE AND
1618 glPsNodeType(glIndexByPsNodeId(glReferenceId(glPsNodeId(i)))) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD)))
1619 AND glParentId(i) = p_ps_node_id)THEN
1620
1621 IF(glPsNodeType(i) = PS_NODE_TYPE_REFERENCE)THEN
1622 v_return(nCount) := GENERATE_NAME_EXPL(ADJUSTED_EXPLOSION(p_expl_id, glPsNodeId(i)), glReferenceId(glPsNodeId(i)));
1623 ELSE
1624 v_return(nCount) := GENERATE_NAME_EXPL(p_expl_id, glPsNodeId(i));
1625 END IF;
1626 nCount := nCount + 1;
1627 END IF;
1628 END LOOP;
1629 END IF;
1630
1631 nDebug := 7004059;
1632
1633 RETURN v_return;
1634 END;
1635 ---------------------------------------------------------------------------------------
1636 FUNCTION GENERATE_ARITHMETIC(j IN PLS_INTEGER) RETURN tStringArray IS
1637
1638 v_return tStringArray;
1639 nChild PLS_INTEGER;
1640 nCount PLS_INTEGER;
1641 lhs tStringArray;
1642 rhs tStringArray;
1643 ListType PLS_INTEGER;
1644 v_rounding VARCHAR2(16) := ' ';
1645 v_target VARCHAR2(4000);
1646 v_parj PLS_INTEGER;
1647 optimizeFlag PLS_INTEGER := 0;
1648
1649 BEGIN
1650
1651 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
1652 RAISE CZ_E_WRONG_ARITHMETIC_OPER;
1653 END IF;
1654
1655 nCount := 1;
1656 nChild := v_ChildrenIndex(v_tExprId(j));
1657 IF(v_tExprParentId.EXISTS(nChild + 1) AND v_tExprParentId(nChild + 1) = v_tExprId(j))THEN
1658 nCount := 2;
1659 END IF;
1660
1661 nDebug := 8004002;
1662
1663 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
1664 nLocalDefaults := nLocalDefaults + 1;
1665 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
1666 v_target := 'TOTAL ' || v_return(1) || NewLine;
1667
1668 --Check if this procedure has been called for generation of a direct child expression of a rounding
1669 --operator. If so, set a flag to generate an enhanced contribute relation and no temporary total.
1670 --If the rounding operator is a root operator of a numeric rule with an advanced lhs expression,
1671 --which is indicated by the optimizeChain flag, generate the optimized contribute relation.
1672
1673 IF(v_tExprParentId(j) IS NOT NULL)THEN
1674
1675 v_parj := v_IndexByExprNodeId(v_tExprParentId(j));
1676
1677 IF(v_tExprType(v_parj) = EXPR_NODE_TYPE_OPERATOR AND
1678 v_tExprSubtype(v_parj) IN (OPERATOR_ROUND, OPERATOR_CEILING, OPERATOR_FLOOR, OPERATOR_TRUNCATE))THEN
1679
1680 v_rounding := OperatorLiterals(v_tExprSubtype(v_parj));
1681 generateRound := OPTIMIZATION_COMPLETED;
1682
1683 IF(optimizeChain = OPTIMIZATION_REQUESTED)THEN
1684
1685 v_return(1) := optimizeTarget;
1686 v_target := NULL;
1687 optimizeChain := OPTIMIZATION_COMPLETED;
1688 END IF;
1689 END IF;
1690 ELSIF(optimizeContribute = OPTIMIZATION_REQUESTED)THEN
1691
1692 optimizeFlag := 1;
1693 optimizeContribute := OPTIMIZATION_COMPLETED;
1694 END IF;
1695
1696 IF(nCount = 1)THEN
1697
1698 nDebug := 8004003;
1699
1700 lhs := GENERATE_EXPRESSION(nChild, ListType);
1701 IF(v_tExprSubtype(j) = OPERATOR_SUB)THEN
1702
1703 IF(optimizeFlag = 0)THEN
1704
1705 vLogicLine := v_target || 'CONTRIBUTE ' || lhs(1) || OperatorLiterals(OPERATOR_MULT) || '-1 ' ||
1706 v_return(1) || v_rounding || '... ' || TO_CHAR(nReasonId) || NewLine;
1707 ELSE
1708
1709 v_return(1) := lhs(1) || OperatorLiterals(OPERATOR_MULT) || '-1 ';
1710 END IF;
1711 ELSE
1712
1713 v_return(1) := lhs(1);
1714 END IF;
1715 ELSE
1716
1717 nDebug := 8004004;
1718
1719 lhs := GENERATE_EXPRESSION(nChild, ListType);
1720
1721 nDebug := 8004005;
1722
1723 rhs := GENERATE_EXPRESSION(nChild + 1, ListType);
1724
1725 nDebug := 8004006;
1726
1727 IF(optimizeFlag = 0)THEN
1728
1729 vLogicLine := v_target || 'CONTRIBUTE ' || lhs(1) || OperatorLiterals(v_tExprSubtype(j)) ||
1730 rhs(1) || ' ' || v_return(1) || v_rounding || '... ' || TO_CHAR(nReasonId) || NewLine;
1731 ELSE
1732
1733 v_return(1) := lhs(1) || OperatorLiterals(v_tExprSubtype(j)) || rhs(1) || ' ';
1734 END IF;
1735 END IF;
1736
1737 PACK;
1738 RETURN v_return;
1739 END;
1740 ---------------------------------------------------------------------------------------
1741 FUNCTION GENERATE_MATH_UNARY(j IN PLS_INTEGER) RETURN tStringArray IS
1742 v_return tStringArray;
1743 v_result tStringArray;
1744 nChild PLS_INTEGER;
1745 ListType PLS_INTEGER;
1746 BEGIN
1747
1748 nDebug := 7000100;
1749
1750 IF((NOT v_ChildrenIndex.EXISTS(v_tExprId(j))) OR v_NumberOfChildren(v_tExprId(j)) <> 1)THEN
1751 nParam := v_tExprSubtype(j);
1752 RAISE CZ_E_MATH_PARAMETERS;
1753 END IF;
1754
1755 nChild := v_ChildrenIndex(v_tExprId(j));
1756
1757 nDebug := 7000101;
1758
1759 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
1760 nLocalDefaults := nLocalDefaults + 1;
1761 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
1762
1763 nDebug := 7000102;
1764
1765 v_result := GENERATE_EXPRESSION(nChild, ListType);
1766
1767 nDebug := 7000103;
1768
1769 vLogicLine := 'TOTAL ' || v_return(1) || NewLine ||
1770 'MF ' || v_result(1) || OperatorLiterals(v_tExprSubtype(j)) ||
1771 v_return(1) || ' ... ' || TO_CHAR(nReasonId) || NewLine;
1772 PACK;
1773
1774 RETURN v_return;
1775 END;
1776 ---------------------------------------------------------------------------------------
1777 FUNCTION GENERATE_MATH_BINARY(j IN PLS_INTEGER) RETURN tStringArray IS
1778 v_return tStringArray;
1779 nChild PLS_INTEGER;
1780 lhs tStringArray;
1781 rhs tStringArray;
1782 ListType PLS_INTEGER;
1783 BEGIN
1784
1785 nDebug := 7000200;
1786
1787 IF((NOT v_ChildrenIndex.EXISTS(v_tExprId(j))) OR v_NumberOfChildren(v_tExprId(j)) <> 2)THEN
1788 nParam := v_tExprSubtype(j);
1789 RAISE CZ_E_MATH_PARAMETERS;
1790 END IF;
1791
1792 nChild := v_ChildrenIndex(v_tExprId(j));
1793
1794 nDebug := 7000201;
1795
1796 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
1797 nLocalDefaults := nLocalDefaults + 1;
1798 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
1799
1800 nDebug := 7000202;
1801
1802 lhs := GENERATE_EXPRESSION(nChild, ListType);
1803
1804 nDebug := 7000203;
1805
1806 rhs := GENERATE_EXPRESSION(nChild + 1, ListType);
1807
1808 --Bug #1990405. For the pow function, the second operand must evaluate to an integer. This
1809 --requirement may be removed or modified later.
1810
1811 IF(v_tExprSubtype(j) = OPERATOR_POW)THEN
1812
1813 --The generated expression should be an integer constant.
1814
1815 IF(REPLACE(TRANSLATE(rhs(1), '0123456789', '0000000000'), '0', NULL) IS NOT NULL)THEN
1816 RAISE CZ_E_INCORRECT_POWER;
1817 END IF;
1818 END IF;
1819
1820 nDebug := 7000204;
1821
1822 vLogicLine := 'TOTAL ' || v_return(1) || NewLine ||
1823 'MF ' || lhs(1) || ' ' || rhs(1) || OperatorLiterals(v_tExprSubtype(j)) ||
1824 v_return(1) || ' ... ' || TO_CHAR(nReasonId) || NewLine;
1825 PACK;
1826
1827 RETURN v_return;
1828 END;
1829 ---------------------------------------------------------------------------------------
1830 FUNCTION GENERATE_MATH_ROUND(j IN PLS_INTEGER) RETURN tStringArray IS
1831 v_return tStringArray;
1832 nChild PLS_INTEGER;
1833 lhs tStringArray;
1834 rhs tStringArray;
1835 ListType PLS_INTEGER;
1836 sReasonId VARCHAR2(4000) := TO_CHAR(nReasonId);
1837 BEGIN
1838
1839 nDebug := 7000300;
1840
1841 IF((NOT v_ChildrenIndex.EXISTS(v_tExprId(j))) OR v_NumberOfChildren(v_tExprId(j)) <> 2)THEN
1842 nParam := v_tExprSubtype(j);
1843 RAISE CZ_E_MATH_PARAMETERS;
1844 END IF;
1845
1846 nChild := v_ChildrenIndex(v_tExprId(j));
1847
1848 nDebug := 7000301;
1849
1850 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
1851 nLocalDefaults := nLocalDefaults + 1;
1852 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
1853
1854 nDebug := 7000302;
1855
1856 lhs := GENERATE_EXPRESSION(nChild, ListType);
1857
1858 nDebug := 7000303;
1859
1860 rhs := GENERATE_EXPRESSION(nChild + 1, ListType);
1861
1862 nDebug := 7000304;
1863
1864 vLogicLine := 'TOTAL ' || v_return(1) || '_1' || NewLine ||
1865 'MF ' || lhs(1) || ' ' || rhs(1) || OperatorLiterals(OPERATOR_MATHDIV) ||
1866 v_return(1) || '_1 ... ' || sReasonId || NewLine;
1867 PACK;
1868 vLogicLine := 'TOTAL ' || v_return(1) || '_2' || NewLine ||
1869 'MF ' || v_return(1) || '_1' || OperatorLiterals(v_tExprSubtype(j)) ||
1870 v_return(1) || '_2 ... ' || sReasonId || NewLine;
1871 PACK;
1872 vLogicLine := 'TOTAL ' || v_return(1) || NewLine ||
1873 'CONTRIBUTE ' || rhs(1) || OperatorLiterals(OPERATOR_MULT) ||
1874 v_return(1) || '_2 ' || v_return(1) || ' ... ' || sReasonId || NewLine;
1875 PACK;
1876
1877 RETURN v_return;
1878 END;
1879 ---------------------------------------------------------------------------------------
1880 FUNCTION GENERATE_LITERAL(j IN PLS_INTEGER) RETURN tStringArray IS
1881 v_return tStringArray;
1882 BEGIN
1883
1884 v_return(1) := v_tExprDataValue(j);
1885
1886 IF(v_tExprDataType(j) = DATA_TYPE_BOOLEAN)THEN
1887 IF(UPPER(v_tExprDataValue(j)) IN ('1', LOGICAL_CONSTANT_TRUE))THEN
1888
1889 v_return(1) := ALWAYS_TRUE;
1890 ELSIF(UPPER(v_tExprDataValue(j)) IN ('0', LOGICAL_CONSTANT_FALSE))THEN
1891
1892 v_return(1) := ALWAYS_FALSE;
1893 END IF;
1894
1895 --Bug #4375977.
1896
1897 IF(v_tLogicNetType(nHeaderId) = LOGIC_NET_TYPE_NETWORK AND (NOT v_IsConnectorNet.EXISTS(v_tExplNodeId(j))))THEN
1898
1899 --If we are generating into a conditional net, we add an extra ^parent to the path, but only if
1900 --this is not a connector's net.
1901
1902 v_return(1) := PATH_DELIMITER || 'parent' || PATH_DELIMITER || v_return(1);
1903 END IF;
1904 END IF;
1905 RETURN v_return;
1906 END;
1907 ---------------------------------------------------------------------------------------
1908 FUNCTION GENERATE_CONSTANT(j IN PLS_INTEGER) RETURN tStringArray IS
1909 v_return tStringArray;
1910 BEGIN
1911 IF(v_tExprSubtype(j) = EXPR_SUBTYPE_CONSTANT_E)THEN
1912
1913 IF(NOT h_HeaderEDefined.EXISTS(nHeaderId))THEN
1914 h_HeaderEDefined(nHeaderId) := 'T_' || TO_CHAR(nHeaderId) || '_E';
1915 vLogicLine := 'TOTAL ' || h_HeaderEDefined(nHeaderId) || ' ' || MATH_CONSTANT_E || NewLine;
1916 PACK;
1917 END IF;
1918 v_return(1) := h_HeaderEDefined(nHeaderId);
1919
1920 ELSIF(v_tExprSubtype(j) = EXPR_SUBTYPE_CONSTANT_PI)THEN
1921
1922 IF(NOT h_HeaderPiDefined.EXISTS(nHeaderId))THEN
1923 h_HeaderPiDefined(nHeaderId) := 'T_' || TO_CHAR(nHeaderId) || '_PI';
1924 vLogicLine := 'TOTAL ' || h_HeaderPiDefined(nHeaderId) || ' ' || MATH_CONSTANT_PI || NewLine;
1925 PACK;
1926 END IF;
1927 v_return(1) := h_HeaderPiDefined(nHeaderId);
1928
1929 ELSE
1930 RAISE CZ_E_UNKNOWN_EXPR_TYPE;
1931 END IF;
1932 RETURN v_return;
1933 END;
1934 ---------------------------------------------------------------------------------------
1935 FUNCTION GENERATE_MINMAX(j IN PLS_INTEGER) RETURN tStringArray IS
1936 v_return tStringArray;
1937 v_child tStringArray;
1938 v_current VARCHAR2(4000);
1939 v_oper VARCHAR2(10) := OperatorLiterals(v_tExprSubtype(j));
1940 v_rounding VARCHAR2(16) := ' ';
1941 v_actual VARCHAR2(16) := ' ';
1942 v_parj PLS_INTEGER;
1943 v_target VARCHAR2(4000);
1944 doOptimize PLS_INTEGER := 0;
1945 v_name VARCHAR2(128);
1946 BEGIN
1947
1948 nLocalDefaults := nLocalDefaults + 1;
1949 v_name := TO_CHAR(nLocalDefaults);
1950
1951 v_child := GENERATE_NODE_CHILDREN(j);
1952 v_return(1) := t_prefix || v_name || '_1';
1953 v_target := 'TOTAL ' || v_return(1) || NewLine;
1954
1955 IF(v_child.COUNT < 2)THEN
1956 RAISE CZ_E_WRONG_MINMAX_OPERATOR;
1957 END IF;
1958
1959 --Check if this procedure has been called for generation of a direct child expression of a rounding
1960 --operator. If so, set a flag to generate an enhanced contribute relation and no temporary total.
1961 --If the rounding operator is a root operator of a numeric rule with an advanced lhs expression,
1962 --which is indicated by the optimizeChain flag, generate the optimized contribute relation.
1963
1964 IF(v_tExprParentId(j) IS NOT NULL)THEN
1965
1966 v_parj := v_IndexByExprNodeId(v_tExprParentId(j));
1967
1968 IF(v_tExprType(v_parj) = EXPR_NODE_TYPE_OPERATOR AND
1969 v_tExprSubtype(v_parj) IN (OPERATOR_ROUND, OPERATOR_CEILING, OPERATOR_FLOOR, OPERATOR_TRUNCATE))THEN
1970
1971 v_rounding := OperatorLiterals(v_tExprSubtype(v_parj));
1972 generateRound := OPTIMIZATION_COMPLETED;
1973
1974 IF(optimizeChain = OPTIMIZATION_REQUESTED)THEN
1975
1976 optimizeChain := OPTIMIZATION_COMPLETED;
1977 doOptimize := 1;
1978 END IF;
1979 END IF;
1980 END IF;
1981
1982 --If the operator has just two operands, only one contribute relation will be generated, prepare
1983 --variables for this relation.
1984
1985 IF(v_child.COUNT = 2)THEN
1986
1987 v_actual := v_rounding;
1988 IF(doOptimize = 1)THEN
1989
1990 v_target := NULL;
1991 v_return(1) := optimizeTarget;
1992 END IF;
1993 END IF;
1994
1995 vLogicLine := v_target || 'CONTRIBUTE ' || v_child(1) || v_oper || v_child(2) || ' ' ||
1996 v_return(1) || v_actual || '... ' || TO_CHAR(nReasonId) || NewLine;
1997
1998 PACK;
1999
2000 v_current := v_return(1);
2001 v_actual := ' ';
2002
2003 FOR i IN 3..v_child.COUNT LOOP
2004
2005 v_return(1) := t_prefix || v_name || '_' || TO_CHAR(i-1);
2006 v_target := 'TOTAL ' || v_return(1) || NewLine;
2007
2008 --If the operator has more than two operands, two or more contribute relations will be
2009 --generated. We want to modify only the last of them, so prepare the variables before
2010 --generating the last one.
2011
2012 IF(i = v_child.COUNT)THEN
2013
2014 v_actual := v_rounding;
2015 IF(doOptimize = 1)THEN
2016
2017 v_target := NULL;
2018 v_return(1) := optimizeTarget;
2019 END IF;
2020 END IF;
2021
2022 vLogicLine := v_target || 'CONTRIBUTE ' || v_child(i) || v_oper || v_current || ' ' ||
2023 v_return(1) || v_actual || '... ' || TO_CHAR(nReasonId) || NewLine;
2024
2025 v_current := v_return(1);
2026 PACK;
2027
2028 END LOOP;
2029 RETURN v_return;
2030 END;
2031 ---------------------------------------------------------------------------------------
2032 FUNCTION GENERATE_OF(j IN PLS_INTEGER) RETURN tStringArray IS
2033 v_return tStringArray;
2034 v_result tIntegerArray;
2035 nChild PLS_INTEGER;
2036 BEGIN
2037
2038 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
2039 RAISE CZ_E_WRONG_OF_OPERATOR;
2040 END IF;
2041
2042 nChild := v_ChildrenIndex(v_tExprId(j));
2043 v_result := EXPAND_NODE(j);
2044
2045 FOR i IN 1..v_result.COUNT LOOP
2046
2047 v_return(i) := GENERATE_NAME_EXPL(v_ExplByPsNodeId(v_result(i)), v_result(i));
2048 END LOOP;
2049
2050 RETURN v_return;
2051 END;
2052 ---------------------------------------------------------------------------------------
2053 FUNCTION GENERATE_NOT(j IN PLS_INTEGER) RETURN tStringArray IS
2054 v_return tStringArray;
2055 nChild PLS_INTEGER;
2056 oper tStringArray;
2057 ListType PLS_INTEGER;
2058 BEGIN
2059
2060 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
2061 RAISE CZ_E_WRONG_NOT_OPERATOR;
2062 END IF;
2063
2064 nChild := v_ChildrenIndex(v_tExprId(j));
2065 IF(v_tExprParentId.EXISTS(nChild + 1) AND v_tExprParentId(nChild + 1) = v_tExprId(j))THEN
2066 RAISE CZ_E_WRONG_NOT_OPERATOR;
2067 END IF;
2068
2069 IF(NOT HAS_LOGICAL_VALUE(nChild))THEN
2070 nParam := j;
2071 RAISE CZ_E_INVALID_OPERAND_TYPE;
2072 END IF;
2073
2074 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
2075 nLocalDefaults := nLocalDefaults + 1;
2076 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
2077
2078 oper := GENERATE_EXPRESSION(nChild, ListType);
2079
2080 vLogicLine := 'OBJECT ' || v_return(1) || NewLine ||
2081 'GS N ... ' || TO_CHAR(nReasonId) || NewLine ||
2082 'GL' || OperatorLetters(OPERATOR_ANYOF) || oper(1) || NewLine ||
2083 'GR' || OperatorLetters(OPERATOR_ANYOF) || v_return(1) || NewLine;
2084 PACK;
2085
2086 RETURN v_return;
2087 END;
2088 ---------------------------------------------------------------------------------------
2089 FUNCTION GENERATE_NOTTRUE(j IN PLS_INTEGER) RETURN tStringArray IS
2090 v_return tStringArray;
2091 nChild PLS_INTEGER;
2092 oper tStringArray;
2093 ListType PLS_INTEGER;
2094 v_NodeId NUMBER; --kdande; Bug 6881902; 11-Mar-2008
2095 v_HeaderId NUMBER;
2096 v_nodename VARCHAR2(4000);
2097 v_accuname VARCHAR2(4000);
2098 iLocal PLS_INTEGER;
2099 BEGIN
2100
2101 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
2102 RAISE CZ_E_WRONG_NOTTRUE_OPERATOR;
2103 END IF;
2104
2105 nChild := v_ChildrenIndex(v_tExprId(j));
2106 IF(v_tExprParentId.EXISTS(nChild + 1) AND v_tExprParentId(nChild + 1) = v_tExprId(j))THEN
2107 RAISE CZ_E_WRONG_NOTTRUE_OPERATOR;
2108 END IF;
2109
2110 IF(NOT HAS_LOGICAL_VALUE(nChild))THEN
2111 nParam := j;
2112 RAISE CZ_E_INVALID_OPERAND_TYPE;
2113 END IF;
2114
2115 --OptimizeNotTrue is a db setting which is disabled by default.
2116
2117 IF(OptimizeNotTrue = 0 OR v_tExprType(nChild) <> EXPR_NODE_TYPE_NODE)THEN
2118
2119 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
2120 nLocalDefaults := nLocalDefaults + 1;
2121 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
2122
2123 oper := GENERATE_EXPRESSION(nChild, ListType);
2124
2125 vLogicLine := 'OBJECT ' || v_return(1) || NewLine ||
2126 'NOTTRUE ' || oper(1) || ' ' || v_return(1) || ' ... ' || TO_CHAR(nReasonId) || NewLine;
2127 PACK;
2128 ELSE
2129
2130 v_NodeId := v_tExprPsNodeId(nChild);
2131
2132 IF((NOT v_HeaderByNotTrueId.EXISTS(v_NodeId)) AND
2133 (glAccumulator(v_NodeId) IS NULL OR glAccumulator(v_NodeId) = FLAG_NO_ACCUMULATOR))THEN
2134
2135 --Need to generate a new NOTTRUE relation in the node's structure file
2136
2137 v_HeaderId := glHeaderByPsNodeId(v_NodeId);
2138 v_nodename := 'P_' || TO_CHAR(glPersistentId(v_NodeId));
2139 v_accuname := v_nodename || '_NT';
2140
2141 --Flush off the buffer because we are about to write to another file
2142
2143 IF(vLogicText IS NOT NULL)THEN
2144 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
2145 (nHeaderId, v_tSequenceNbr(nHeaderId), vLogicText);
2146 vLogicText := NULL;
2147 v_tSequenceNbr(nHeaderId) := v_tSequenceNbr(nHeaderId) + 1;
2148 END IF;
2149
2150 --Fix for the bug #2398832 - we may be re-using the accumulator, so we should not
2151 --assign to it effectivities and usages of a particular node.
2152 --Do not write the effectivity dates using the actual effective date interval of
2153 --the corresponding node.
2154
2155 --iLocal := glIndexByPsNodeId(v_NodeId);
2156 --CurrentEffFrom := glEffFrom(iLocal);
2157 --CurrentEffUntil := glEffUntil(iLocal);
2158 --CurrentUsageMask := glUsageMask(iLocal);
2159
2160 --Instead make the accumulator always effective and universal.
2161
2162 CurrentEffFrom := EpochBeginDate;
2163 CurrentEffUntil := EpochEndDate;
2164 CurrentUsageMask := AnyUsageMask;
2165
2166 IF((NOT h_EffFrom.EXISTS(v_HeaderId)) OR
2167 (h_EffFrom(v_HeaderId) <> CurrentEffFrom OR h_EffUntil(v_HeaderId) <> CurrentEffUntil OR
2168 h_EffUsageMask(v_HeaderId) <> CurrentUsageMask))THEN
2169
2170 h_EffFrom(v_HeaderId) := CurrentEffFrom;
2171 h_EffUntil(v_HeaderId) := CurrentEffUntil;
2172 h_EffUsageMask(v_HeaderId) := CurrentUsageMask;
2173
2174 vLogicText := LTRIM(CurrentUsageMask, '0');
2175 IF(vLogicText IS NOT NULL) THEN
2176 vLogicText := EffUsagePrefix || vLogicText;
2177 END IF;
2178
2179 IF(CurrentEffFrom = EpochBeginDate)THEN
2180 CurrentFromDate := NULL;
2181 ELSE
2182 CurrentFromDate := TO_CHAR(CurrentEffFrom, EffDateFormat);
2183 END IF;
2184
2185 IF(CurrentEffUntil = EpochEndDate)THEN
2186 CurrentUntilDate := NULL;
2187 ELSE
2188 CurrentUntilDate := TO_CHAR(CurrentEffUntil, EffDateFormat);
2189 END IF;
2190
2191 vLogicText := 'EFF ' || CurrentFromDate || ', ' || CurrentUntilDate || ', ' || vLogicText || NewLine;
2192 END IF;
2193
2194 vLogicText := vLogicText || 'OBJECT ' || v_accuname || NewLine ||
2195 'NOTTRUE ' || v_nodename || ' ' || v_accuname || ' ... ' || TO_CHAR(nReasonId) || NewLine;
2196
2197 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
2198 (v_HeaderId, vSeqNbrByHeader(v_HeaderId), vLogicText);
2199 vLogicText := NULL;
2200 vSeqNbrByHeader(v_HeaderId) := vSeqNbrByHeader(v_HeaderId) + 1;
2201
2202 v_HeaderByNotTrueId(v_NodeId) := v_HeaderId;
2203
2204 --Part of the fix for the bug #2857955. We will never be here if glAccumulator(v_NodeId) was
2205 --FLAG_ACCUMULATOR_NT because the accumulator would have already been created.
2206
2207 UPDATE cz_ps_nodes SET
2208 accumulator_flag = DECODE(glAccumulator(v_NodeId), FLAG_ACCUMULATOR_ACC, FLAG_ACCUMULATOR_BOTH, FLAG_ACCUMULATOR_NT)
2209 WHERE ps_node_id = v_NodeId;
2210
2211 END IF;
2212
2213 v_return(1) := GENERATE_NAME(nChild, v_NodeId) || '_NT';
2214 END IF;
2215
2216 RETURN v_return;
2217 END;
2218 ---------------------------------------------------------------------------------------
2219 FUNCTION COMPARE_VALUES(val1 IN VARCHAR2, val2 IN VARCHAR2, OperType IN PLS_INTEGER)
2220 RETURN BOOLEAN IS
2221 v_null NUMBER;
2222 BEGIN
2223 IF(OperType = OPERATOR_EQUALS)THEN
2224 RETURN (val1 = val2);
2225 ELSIF(OperType = OPERATOR_NOTEQUALS)THEN
2226 RETURN (val1 <> val2);
2227 ELSIF(OperType = OPERATOR_EQUALS_INT)THEN
2228 RETURN (val1 = val2);
2229 ELSIF(OperType = OPERATOR_NOTEQUALS_INT)THEN
2230 RETURN (val1 <> val2);
2231 ELSIF(OperType = OPERATOR_GT)THEN
2232 RETURN (val1 > val2);
2233 ELSIF(OperType = OPERATOR_LT)THEN
2234 RETURN (val1 < val2);
2235 ELSIF(OperType = OPERATOR_GE)THEN
2236 RETURN (val1 >= val2);
2237 ELSIF(OperType = OPERATOR_LE)THEN
2238 RETURN (val1 <= val2);
2239 ELSIF(OperType = OPERATOR_BEGINSWITH)THEN
2240 RETURN (INSTR(val1, val2) = 1);
2241 ELSIF(OperType = OPERATOR_ENDSWITH)THEN
2242 RETURN (INSTR(val1, val2, -1) = (LENGTH(val1) - LENGTH(val2) + 1));
2243 ELSIF(OperType = OPERATOR_CONTAINS)THEN
2244 RETURN (INSTR(val1, val2) <> 0);
2245 ELSIF(OperType = OPERATOR_LIKE)THEN
2246 BEGIN
2247 SELECT NULL INTO v_null FROM DUAL WHERE val1 LIKE val2;
2248 RETURN TRUE;
2249 EXCEPTION
2250 WHEN NO_DATA_FOUND THEN
2251 RETURN FALSE;
2252 END;
2253 ELSIF(OperType = OPERATOR_MATCHES)THEN
2254 BEGIN
2255 SELECT NULL INTO v_null FROM DUAL WHERE val1 LIKE val2;
2256 RETURN TRUE;
2257 EXCEPTION
2258 WHEN NO_DATA_FOUND THEN
2259 RETURN FALSE;
2260 END;
2261 ELSIF(OperType = OPERATOR_DOESNOTBEGINWITH)THEN
2262 RETURN (INSTR(val1, val2) <> 1);
2263 ELSIF(OperType = OPERATOR_DOESNOTENDWITH)THEN
2264 RETURN (INSTR(val1, val2, -1) <> (LENGTH(val1) - LENGTH(val2) + 1));
2265 ELSIF(OperType = OPERATOR_DOESNOTCONTAIN)THEN
2266 RETURN (INSTR(val1, val2) = 0);
2267 ELSIF(OperType = OPERATOR_NOTLIKE)THEN
2268 BEGIN
2269 SELECT NULL INTO v_null FROM DUAL WHERE val1 NOT LIKE val2;
2270 RETURN TRUE;
2271 EXCEPTION
2272 WHEN NO_DATA_FOUND THEN
2273 RETURN FALSE;
2274 END;
2275 ELSE
2276 RAISE CZ_E_WRONG_COMPARISON_OPER;
2277 END IF;
2278 END;
2279 ---------------------------------------------------------------------------------------
2280 FUNCTION EXTRACT_PROPERTY_VALUE(inVal IN VARCHAR2, inType IN PLS_INTEGER)
2281 RETURN VARCHAR2 IS
2282 BEGIN
2283 IF(inType = DATATYPE_STRING)THEN
2284 RETURN SUBSTR(inVal, INSTR(inVal, PROPERTY_DELIMITER) + 1);
2285 ELSE
2286 RETURN inVal;
2287 END IF;
2288 END;
2289 ---------------------------------------------------------------------------------------
2290 FUNCTION EXTRACT_PROPERTY_VALUE(inVal IN VARCHAR2)
2291
2292 --This simplified version is used in GENERATE_REFNODE to extract boolean property values
2293 --represented as character '0'/'1' in the database.
2294
2295 RETURN VARCHAR2 IS
2296 BEGIN
2297 RETURN SUBSTR(inVal, INSTR(inVal, PROPERTY_DELIMITER) + 1);
2298 END;
2299 ---------------------------------------------------------------------------------------
2300 FUNCTION EXTRACT_PROPERTY_NODE(inVal IN VARCHAR2) RETURN VARCHAR2 IS
2301 BEGIN
2302 RETURN SUBSTR(inVal, 1, INSTR(inVal, PROPERTY_DELIMITER) - 1);
2303 END;
2304 ---------------------------------------------------------------------------------------
2305 FUNCTION GENERATE_CONCAT(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
2306 v_return tStringArray;
2307 nChild PLS_INTEGER;
2308 lhs tStringArray;
2309 rhs tStringArray;
2310 lListType PLS_INTEGER;
2311 rListType PLS_INTEGER;
2312 ExprId PLS_INTEGER := v_tExprId(j);
2313 BEGIN
2314
2315 IF(NOT v_ChildrenIndex.EXISTS(ExprId))THEN
2316 RAISE CZ_E_WRONG_COMPARISON_OPER;
2317 END IF;
2318
2319 nChild := v_ChildrenIndex(ExprId);
2320 IF(NOT v_tExprParentId.EXISTS(nChild + 1) OR v_tExprParentId(nChild + 1) IS NULL OR
2321 v_tExprParentId(nChild + 1) <> ExprId)THEN
2322 RAISE CZ_E_WRONG_COMPARISON_OPER;
2323 END IF;
2324
2325 lhs := GENERATE_EXPRESSION(nChild, lListType);
2326 rhs := GENERATE_EXPRESSION(nChild+1, rListType);
2327
2328 v_return(1) := EXTRACT_PROPERTY_VALUE(lhs(1)) || EXTRACT_PROPERTY_VALUE(rhs(1));
2329 ListType := DATA_TYPE_TEXT;
2330 RETURN v_return;
2331 END;
2332 ---------------------------------------------------------------------------------------
2333 --Bug 5620750 - function to generate the new ToText operator when used outside of PBC
2334 --context.
2335
2336 FUNCTION GENERATE_TOTEXT(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
2337 v_return tStringArray;
2338 ExprId PLS_INTEGER := v_tExprId(j);
2339 BEGIN
2340
2341 IF((NOT v_ChildrenIndex.EXISTS(ExprId)) OR v_NumberOfChildren(ExprId) <> 1)THEN
2342 RAISE CZ_R_WRONG_EXPRESSION_NODE;
2343 END IF;
2344
2345 v_return(1) := TO_CHAR(v_tExprDataNumValue(v_ChildrenIndex(ExprId)));
2346 ListType := DATA_TYPE_TEXT;
2347 RETURN v_return;
2348 END;
2349 ---------------------------------------------------------------------------------------
2350 FUNCTION GENERATE_COMPARE(j IN PLS_INTEGER) RETURN tStringArray IS
2351 v_return tStringArray;
2352 v_left tStringArray;
2353 nChild PLS_INTEGER;
2354 lhs tStringArray;
2355 rhs tStringArray;
2356 lListType PLS_INTEGER;
2357 rListType PLS_INTEGER;
2358 OperType PLS_INTEGER := v_tExprSubtype(j);
2359 ExprId PLS_INTEGER := v_tExprId(j);
2360 nCount PLS_INTEGER := 1;
2361 BEGIN
2362
2363 IF(NOT v_ChildrenIndex.EXISTS(ExprId))THEN
2364 RAISE CZ_E_WRONG_COMPARISON_OPER;
2365 END IF;
2366
2367 nChild := v_ChildrenIndex(ExprId);
2368 IF(NOT v_tExprParentId.EXISTS(nChild + 1) OR v_tExprParentId(nChild + 1) IS NULL OR
2369 v_tExprParentId(nChild + 1) <> ExprId)THEN
2370 RAISE CZ_E_WRONG_COMPARISON_OPER;
2371 END IF;
2372
2373 nDebug := 8001120;
2374
2375 --v_return(1) := 'T_' || TO_CHAR(ExprId);
2376 nLocalDefaults := nLocalDefaults + 1;
2377 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
2378
2379 nDebug := 8001121;
2380
2381 generateCompare := 1;
2382 lhs := GENERATE_EXPRESSION(nChild, lListType);
2383
2384 nDebug := 8001122;
2385
2386 rhs := GENERATE_EXPRESSION(nChild+1, rListType);
2387 generateCompare := 0;
2388
2389 --Bug #4191838.
2390
2391 IF(lhs.COUNT = 1 AND lListType = DATA_TYPE_TEXT AND rhs.COUNT = 1 AND rListType = DATA_TYPE_TEXT)THEN
2392
2393 v_left(1) := 'OBJECT ' || v_return(1) || NewLine;
2394 v_left(2) := TO_CHAR(nReasonId) || NewLine ||
2395 'GL' || OperatorLetters(OPERATOR_ALLOF) || ALWAYS_TRUE || NewLine ||
2396 'GR' || OperatorLetters(OPERATOR_ALLOF) || v_return(1) || NewLine;
2397
2398 IF(COMPARE_VALUES(EXTRACT_PROPERTY_VALUE(lhs(1), lListType),
2399 EXTRACT_PROPERTY_VALUE(rhs(1), rListType), OperType))THEN
2400 vLogicLine := v_left(1) || 'GS R ... ' || v_left(2);
2401 ELSE
2402 vLogicLine := v_left(1) || 'GS E ... ' || v_left(2);
2403 END IF;
2404 PACK;
2405 RETURN v_return;
2406 END IF;
2407
2408 nDebug := 8001123;
2409
2410 IF(lListType = DATATYPE_STRING OR rListType = DATATYPE_STRING)THEN
2411
2412 nDebug := 8001124;
2413
2414 FOR ii IN 1..lhs.COUNT LOOP
2415 FOR jj IN 1..rhs.COUNT LOOP
2416
2417 IF(COMPARE_VALUES(EXTRACT_PROPERTY_VALUE(lhs(ii), lListType),
2418 EXTRACT_PROPERTY_VALUE(rhs(jj), rListType), OperType))THEN
2419 IF(lListType = DATATYPE_STRING AND rListType = DATATYPE_STRING)THEN
2420
2421 nDebug := 8001125;
2422
2423 v_left(nCount) := v_return(1) || '_' || TO_CHAR(nCount);
2424
2425 vLogicLine := 'OBJECT ' || v_left(nCount) || NewLine ||
2426 'GS R ' || sUnsatisfiedId || '... ' || TO_CHAR(nReasonId) || NewLine ||
2427 'GL' || OperatorLetters(OPERATOR_ALLOF) ||
2428 EXTRACT_PROPERTY_NODE(lhs(ii)) || ' ' || EXTRACT_PROPERTY_NODE(rhs(jj)) || NewLine ||
2429 'GR' || OperatorLetters(OPERATOR_ALLOF) || v_left(nCount) || NewLine;
2430 PACK;
2431 nCount := nCount + 1;
2432
2433 ELSIF(lListType = DATATYPE_STRING)THEN
2434
2435 nDebug := 8001126;
2436
2437 v_left(nCount) := EXTRACT_PROPERTY_NODE(lhs(ii));
2438 nCount := nCount + 1;
2439
2440 ELSIF(rListType = DATATYPE_STRING)THEN
2441
2442 nDebug := 8001127;
2443
2444 v_left(nCount) := EXTRACT_PROPERTY_NODE(rhs(jj));
2445 nCount := nCount + 1;
2446
2447 END IF;
2448 END IF;
2449 END LOOP;
2450 END LOOP;
2451
2452 nDebug := 8001128;
2453
2454 IF(v_left.COUNT = 0)THEN
2455
2456 vLogicLine := 'OBJECT ' || v_return(1) || NewLine ||
2457 'GS E ...' || TO_CHAR(nReasonId) || NewLine ||
2458 'GL' || OperatorLetters(OPERATOR_ALLOF) || ALWAYS_TRUE || NewLine ||
2459 'GR' || OperatorLetters(OPERATOR_ALLOF) || v_return(1) || NewLine;
2460
2461 ELSE
2462
2463 localString := NULL;
2464 IF(v_left.COUNT > 1)THEN localString := sUnsatisfiedId; END IF;
2465
2466 vLogicLine := 'OBJECT ' || v_return(1) || NewLine ||
2467 'GS R ' || localString || '... ' || TO_CHAR(nReasonId) || NewLine ||
2468 'GL' || OperatorLetters(OPERATOR_ANYOF);
2469
2470 PACK;
2471
2472 nDebug := 8001129;
2473
2474 FOR i IN 1..v_left.COUNT LOOP
2475
2476 vLogicLine := v_left(i) || ' ';
2477 PACK;
2478
2479 END LOOP;
2480
2481 vLogicLine := NewLine || 'GR' || OperatorLetters(OPERATOR_ALLOF) || v_return(1) || NewLine;
2482
2483 nDebug := 8001130;
2484
2485 END IF;
2486
2487 ELSE
2488
2489 nDebug := 8001131;
2490
2491 vLogicLine := 'OBJECT ' || v_return(1) || NewLine ||
2492 'COMPARE ' || lhs(1) || OperatorLiterals(OperType) ||
2493 rhs(1) || ' ' || v_return(1) || ' ... ' || TO_CHAR(nReasonId) || NewLine;
2494 END IF;
2495
2496 PACK;
2497
2498 RETURN v_return;
2499 END;
2500 ---------------------------------------------------------------------------------------
2501 FUNCTION GENERATE_ANYALLOF(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
2502 v_return tStringArray;
2503 v_child tStringArray;
2504 v_parentid PLS_INTEGER;
2505 v_parj PLS_INTEGER;
2506 nChild PLS_INTEGER;
2507 BEGIN
2508
2509 --nDebug := 7000001;
2510
2511 --Bug #5015333 - need a verification for the logical nature of the operands.
2512
2513 nChild := v_ChildrenIndex(v_tExprId(j));
2514
2515 WHILE(v_tExprParentId(nChild) = v_tExprId(j)) LOOP
2516
2517 IF(NOT HAS_LOGICAL_VALUE(nChild))THEN
2518
2519 nParam := j;
2520 RAISE CZ_E_INVALID_OPERAND_TYPE;
2521 END IF;
2522
2523 nChild := nChild + 1;
2524 END LOOP;
2525
2526 v_child := GENERATE_NODE_CHILDREN(j);
2527 v_parentid := v_tExprParentId(j);
2528
2529 --This is important that this assignment goes after the node children generation, because the
2530 --type of the parent operator can be changed during the children generation in some cases
2531 --(see internal case #3 below).
2532
2533 ListType := v_tExprSubtype(j);
2534
2535 IF(OptimizeAllAnyOf = 1)THEN
2536 IF(v_parentid IS NOT NULL)THEN
2537
2538 v_parj := v_IndexByExprNodeId(v_parentid);
2539
2540 IF(v_tExprType(v_parj) = EXPR_NODE_TYPE_OPERATOR AND
2541 v_tExprSubtype(v_parj) IN (OPERATOR_ANYOF, OPERATOR_ALLOF))THEN
2542
2543 IF(ListType = v_tExprSubtype(v_parj))THEN
2544
2545 --AllOf(AllOf(...) , ...), AnyOf(AnyOf(...) , ...).
2546 --Internal case #1.
2547
2548 return v_child;
2549 ELSIF(v_child.COUNT = 1)THEN
2550
2551 --This operator is either AnyOf or AllOf. It is different from the parent operator which
2552 --is also AnyOf or AllOf. Therefore, this is AllOf(AnyOf(...) , ...) or
2553 --AnyOf(AllOf(...) , ...). If only one child has been generated for this operator than
2554 --we have the case of AllOf(AnyOf(1) , ...) or AnyOf(AllOf(1) , ...).
2555 --Internal case #2.
2556
2557 return v_child;
2558
2559 ELSIF(v_NumberOfChildren(v_parentid) = 1)THEN
2560
2561 --We have AllOf(AnyOf(...)) or AnyOf(AllOf(...)), i. e. this AllOf or AnyOf operator is
2562 --the only child of its parent.If so, we not only carry over the children list but also
2563 --reverse the type of the parent operator.
2564 --Internal case #3.
2565
2566 v_tExprSubtype(v_parj) := ListType;
2567 return v_child;
2568 END IF;
2569 END IF;
2570 ELSIF(nRuleType = RULE_TYPE_LOGIC_RULE)THEN
2571 IF(nRuleOperator <> RULE_OPERATOR_DEFAULTS OR j = jConsequentRoot)THEN
2572 return v_child;
2573 ELSIF(v_child.COUNT = 1)THEN
2574 return v_child;
2575 END IF;
2576 END IF;
2577 END IF;
2578
2579 --nDebug := 7000002;
2580
2581 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
2582 nLocalDefaults := nLocalDefaults + 1;
2583 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
2584
2585 --nDebug := 7000003;
2586
2587 localString := NULL;
2588 IF(v_child.COUNT > 1)THEN localString := sUnsatisfiedId; END IF;
2589
2590 vLogicLine := 'OBJECT ' || v_return(1) || NewLine ||
2591 'GS R ' || localString || '... ' || TO_CHAR(nReasonId) || NewLine ||
2592 'GL' || OperatorLetters(ListType);
2593
2594 PACK;
2595
2596 IF(ChangeChildrenOrder = 1)THEN
2597 FOR i IN REVERSE 1..v_child.COUNT LOOP
2598
2599 vLogicLine := v_child(i) || ' ';
2600 PACK;
2601
2602 END LOOP;
2603 ELSE
2604 FOR i IN 1..v_child.COUNT LOOP
2605
2606 vLogicLine := v_child(i) || ' ';
2607 PACK;
2608
2609 END LOOP;
2610 END IF;
2611
2612 --nDebug := 7000004;
2613
2614 vLogicLine := NewLine || 'GR' || OperatorLetters(OPERATOR_ALLOF) || v_return(1) || NewLine;
2615 PACK;
2616 RETURN v_return;
2617 END;
2618 ---------------------------------------------------------------------------------------
2619 FUNCTION GENERATE_ANDOR(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
2620 v_return tStringArray;
2621 nChild PLS_INTEGER;
2622 lhs tStringArray;
2623 rhs tStringArray;
2624 lListType PLS_INTEGER;
2625 rListType PLS_INTEGER;
2626 BEGIN
2627
2628 IF((NOT v_ChildrenIndex.EXISTS(v_tExprId(j))) OR v_NumberOfChildren(v_tExprId(j)) <> 2)THEN
2629 RAISE CZ_E_WRONG_ANDOR_OPERATOR;
2630 END IF;
2631
2632 nChild := v_ChildrenIndex(v_tExprId(j));
2633
2634 IF(NOT (HAS_LOGICAL_VALUE(nChild) AND HAS_LOGICAL_VALUE(nChild + 1)))THEN
2635 nParam := j;
2636 RAISE CZ_E_INVALID_OPERAND_TYPE;
2637 END IF;
2638
2639 IF(OptimizeAllAnyOf = 1)THEN
2640 IF(v_tExprSubtype(j) = OPERATOR_AND)THEN
2641 v_tExprSubtype(j) := OPERATOR_ALLOF;
2642 ELSE
2643 v_tExprSubtype(j) := OPERATOR_ANYOF;
2644 END IF;
2645 RETURN GENERATE_ANYALLOF(j, ListType);
2646 END IF;
2647
2648 nDebug := 8001700;
2649
2650 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
2651 nLocalDefaults := nLocalDefaults + 1;
2652 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
2653
2654 lhs := GENERATE_EXPRESSION(nChild, lListType);
2655 rhs := GENERATE_EXPRESSION(nChild+1, rListType);
2656
2657 nDebug := 8001701;
2658
2659 vLogicLine := 'OBJECT ' || v_return(1) || NewLine ||
2660 'GS R ' || sUnsatisfiedId || '... ' || TO_CHAR(nReasonId) || NewLine ||
2661 'GL' || OperatorLetters(v_tExprSubtype(j)) || lhs(1) || ' ' || rhs(1) || NewLine ||
2662 'GR' || OperatorLetters(OPERATOR_ANYOF) || v_return(1) || NewLine;
2663 PACK;
2664
2665 nDebug := 8001702;
2666
2667 RETURN v_return;
2668 END;
2669 ---------------------------------------------------------------------------------------
2670 FUNCTION GENERATE_ROUND(j IN PLS_INTEGER) RETURN tStringArray IS
2671 v_return tStringArray;
2672 nChild PLS_INTEGER;
2673 oper tStringArray;
2674 ListType PLS_INTEGER;
2675 BEGIN
2676
2677 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
2678 RAISE CZ_E_WRONG_ROUND_OPERATOR;
2679 END IF;
2680
2681 nChild := v_ChildrenIndex(v_tExprId(j));
2682 IF(v_tExprParentId.EXISTS(nChild + 1) AND v_tExprParentId(nChild + 1)= v_tExprId(j))THEN
2683
2684 RAISE CZ_E_WRONG_ROUND_OPERATOR;
2685 END IF;
2686
2687 generateRound := OPTIMIZATION_REQUESTED;
2688
2689 oper := GENERATE_EXPRESSION(nChild, ListType);
2690
2691 --The value may have been changed by the child expression generation. In this case we are
2692 --optimizing and do not want the increment relation to be generated at all.
2693
2694 IF(generateRound = OPTIMIZATION_REQUESTED)THEN
2695
2696 --v_return(1) := 'T_' || TO_CHAR(v_tExprId(j));
2697 nLocalDefaults := nLocalDefaults + 1;
2698 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
2699
2700 vLogicLine := 'TOTAL ' || v_return(1) || NewLine || 'INC ' || oper(1) || ' ' || v_return(1) ||
2701 OperatorLiterals(v_tExprSubtype(j)) || '... ' || TO_CHAR(nReasonId) || NewLine;
2702 PACK;
2703 generateRound := OPTIMIZATION_COMPLETED;
2704 ELSE
2705
2706 v_return(1) := oper(1);
2707 END IF;
2708
2709 RETURN v_return;
2710 END;
2711 ---------------------------------------------------------------------------------------
2712 FUNCTION PROPERTY_VALUE(j IN PLS_INTEGER, iPSN IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER)
2713 RETURN VARCHAR2 IS
2714 v_return VARCHAR2(4000);
2715 nChild NUMBER;
2716 c_values refCursor;
2717 optionId cz_ps_nodes.ps_node_id%TYPE := glPsNodeId(iPSN);
2718 propertyId cz_expression_nodes.property_id%TYPE := v_tExprPropertyId(j);
2719 itemId cz_ps_nodes.item_id%TYPE := glItemId(iPSN);
2720 sysPropName VARCHAR2(30);
2721 BEGIN
2722
2723 IF(v_tExprType(j) = EXPR_SYS_PROP)THEN
2724
2725 IF(NOT h_SeededName.EXISTS(v_tExprSubtype(j)))THEN RAISE CZ_E_BAD_PROPERTY_TYPE; END IF;
2726 sysPropName := h_SeededName(v_tExprSubtype(j));
2727
2728 IF(sysPropName = RULE_SYS_PROP_NAME)THEN
2729
2730 --nDebug := 8001160;
2731
2732 v_return := glName(iPSN);
2733 ListType := DATATYPE_STRING;
2734
2735 ELSIF(sysPropName = RULE_SYS_PROP_QUANTITY)THEN
2736
2737 --Related bug: #2317427.
2738
2739 v_return := GENERATE_NAME(j, optionId);
2740 ListType := DATATYPE_INTEGER;
2741
2742 ELSIF(sysPropName = RULE_SYS_PROP_INSTANCECOUNT)THEN
2743
2744 --nDebug := 8001161;
2745
2746 --If it is a non-virtual component/product/reference, we add _ACTUALCOUNT to the name.
2747 --If it is a virtual component/product/reference, we return '1'.
2748 --If it is an option, we just generate the name.
2749
2750 IF(glPsNodeType(iPSN) IN (PS_NODE_TYPE_COMPONENT,
2751 PS_NODE_TYPE_REFERENCE,
2752 PS_NODE_TYPE_PRODUCT))THEN
2753 IF(glVirtualFlag(iPSN) = FLAG_NON_VIRTUAL)THEN
2754 v_return := GENERATE_NAME(j, optionId)||'_ACTUALCOUNT';
2755 ELSE
2756 v_return := '1';
2757 END IF;
2758 ELSE
2759 v_return := GENERATE_NAME(j, optionId);
2760 END IF;
2761 ListType := DATATYPE_INTEGER;
2762
2763 --nDebug := 8001162;
2764
2765 ELSIF(sysPropName = RULE_SYS_PROP_MININSTANCE)THEN
2766
2767 --nDebug := 8001163;
2768
2769 v_return := GENERATE_NAME(j, optionId)||'_MIN';
2770 ListType := DATATYPE_INTEGER;
2771
2772 ELSIF(sysPropName = RULE_SYS_PROP_MAXINSTANCE)THEN
2773
2774 --nDebug := 8001164;
2775
2776 v_return := GENERATE_NAME(j, optionId)||'_MAX';
2777 ListType := DATATYPE_INTEGER;
2778
2779 ELSE
2780
2781 RAISE CZ_E_BAD_PROPERTY_TYPE;
2782 END IF;
2783 ELSE
2784
2785 BEGIN
2786
2787 --nDebug := 8001165;
2788
2789 v_return := GET_PROPERTY_VALUE(optionId, propertyId, itemId, ListType);
2790
2791 IF(v_return IS NULL)THEN RAISE CZ_E_NULL_PROPERTY_VALUE; END IF;
2792
2793 IF(ListType IN (DATATYPE_INTEGER, DATATYPE_FLOAT))THEN
2794
2795 BEGIN
2796 nChild := TO_NUMBER(v_return);
2797 EXCEPTION
2798 WHEN OTHERS THEN
2799
2800 SELECT name INTO errorMessage
2801 FROM cz_properties
2802 WHERE property_id = propertyId;
2803
2804 localString := v_return;
2805 RAISE CZ_R_INCORRECT_DATA_TYPE;
2806 END;
2807 END IF;
2808
2809 EXCEPTION
2810 WHEN NO_DATA_FOUND THEN
2811 RAISE CZ_E_NO_SUCH_PROPERTY;
2812 WHEN TOO_MANY_ROWS THEN
2813 RAISE CZ_E_INCORRECT_PROPERTY;
2814 WHEN OTHERS THEN
2815 RAISE;
2816 END;
2817 END IF;
2818
2819 RETURN v_return;
2820 END;
2821 ---------------------------------------------------------------------------------------
2822 FUNCTION STATIC_SYSPROP_VALUE(p_node_id IN NUMBER, p_rule_id IN NUMBER, p_parent_up IN PLS_INTEGER)
2823 RETURN VARCHAR2 IS
2824
2825 optionIndex PLS_INTEGER;
2826 v_step PLS_INTEGER := p_parent_up;
2827 sysPropName cz_rules.name%TYPE;
2828 v_return VARCHAR2(4000);
2829 BEGIN
2830
2831 sysPropName := h_SeededName(p_rule_id);
2832 errorMessage := h_ReportName(p_rule_id);
2833 optionIndex := glIndexByPsNodeId(p_node_id);
2834
2835 BEGIN
2836 WHILE(v_step > 1)LOOP
2837 optionIndex := glIndexByPsNodeId(glParentId(optionIndex));
2838 v_step := v_step - 1;
2839 END LOOP;
2840 EXCEPTION
2841 WHEN OTHERS THEN
2842 RAISE CZ_E_INCORRECT_PROPERTY;
2843 END;
2844
2845 IF(sysPropName = RULE_SYS_PROP_NAME)THEN
2846
2847 v_return := glName(optionIndex);
2848
2849 ELSIF(sysPropName IN (RULE_SYS_PROP_MINVALUE, RULE_SYS_PROP_MINQUANTITY, RULE_SYS_PROP_MINSELECTED))THEN
2850
2851 v_return := glMinimum(optionIndex);
2852
2853 ELSIF(sysPropName IN (RULE_SYS_PROP_MAXVALUE, RULE_SYS_PROP_MAXQUANTITY, RULE_SYS_PROP_MAXSELECTED))THEN
2854
2855 v_return := glMaximum(optionIndex);
2856
2857 ELSIF(sysPropName = RULE_SYS_PROP_DESCRIPTION)THEN
2858
2859 RAISE CZ_E_DESCRIPTION_IN_WHERE;
2860 ELSE
2861
2862 RAISE CZ_E_PROPERTY_NOT_STATIC;
2863 END IF;
2864
2865 RETURN v_return;
2866 END;
2867 ---------------------------------------------------------------------------------------
2868 FUNCTION SYSTEM_PROPERTY_VALUE(j IN PLS_INTEGER, iPSN IN tStringArray, ListType OUT NOCOPY PLS_INTEGER)
2869 RETURN tStringArray IS
2870
2871 v_return tStringArray;
2872 v_result tStringArray;
2873 optionId cz_ps_nodes.ps_node_id%TYPE;
2874 propertyId cz_expression_nodes.property_id%TYPE := v_tExprPropertyId(j);
2875 itemId cz_ps_nodes.item_id%TYPE;
2876 c_values refCursor;
2877 nChild NUMBER;
2878 optionIndex PLS_INTEGER;
2879 sysPropName VARCHAR2(30);
2880 BEGIN
2881
2882 nDebug := 9001000;
2883
2884 FOR i IN 1..iPSN.COUNT LOOP
2885
2886 optionId := TO_NUMBER(iPSN(i));
2887 optionIndex := glIndexByPsNodeId(optionId);
2888
2889 IF(v_tExprType(j) = EXPR_NODE_TYPE_SYSPROP)THEN
2890
2891 sysPropName := h_SeededName(v_tExprSubtype(j));
2892
2893 IF(sysPropName = RULE_SYS_PROP_NAME)THEN
2894
2895 v_return(i) := glName(optionIndex);
2896 ListType := DATA_TYPE_TEXT;
2897
2898 ELSIF(sysPropName = RULE_SYS_PROP_DESCRIPTION)THEN
2899
2900 v_return(i) := glName(optionIndex);
2901 ListType := DATA_TYPE_TEXT;
2902
2903 ELSIF(sysPropName = RULE_SYS_PROP_PARENT)THEN
2904
2905 v_return(i) := TO_CHAR(glParentId(optionIndex));
2906 ListType := DATA_TYPE_NODE;
2907
2908 ELSIF(sysPropName = RULE_SYS_PROP_OPTIONS)THEN
2909
2910 v_result.DELETE;
2911 v_result := GENERATE_CHILDRENOF(v_tExplNodeId(j), TO_NUMBER(iPSN(i)));
2912
2913 FOR ii IN 1..v_result.COUNT LOOP
2914 v_return(v_return.COUNT + 1) := v_result(ii);
2915 END LOOP;
2916 ListType := DATA_TYPE_NODE_COLL;
2917
2918 ELSIF(sysPropName = RULE_SYS_PROP_MINVALUE)THEN
2919
2920 v_return(i) := GENERATE_NAME(j, optionId)||'_MIN';
2921 ListType := DATA_TYPE_INTEGER;
2922
2923 ELSIF(sysPropName = RULE_SYS_PROP_MAXVALUE)THEN
2924
2925 v_return(i) := GENERATE_NAME(j, optionId)||'_MAX';
2926 ListType := DATA_TYPE_INTEGER;
2927
2928 ELSIF(sysPropName = RULE_SYS_PROP_MINQUANTITY)THEN
2929
2930 v_return(i) := TO_CHAR(glMinimum(optionIndex));
2931 ListType := DATA_TYPE_INTEGER;
2932
2933 ELSIF(sysPropName = RULE_SYS_PROP_MAXQUANTITY)THEN
2934
2935 v_return(i) := TO_CHAR(glMaximum(optionIndex));
2936 ListType := DATA_TYPE_INTEGER;
2937
2938 ELSIF(sysPropName = RULE_SYS_PROP_MINSELECTED)THEN
2939
2940 v_return(i) := TO_CHAR(glMinimumSel(optionIndex));
2941 ListType := DATA_TYPE_INTEGER;
2942
2943 ELSIF(sysPropName = RULE_SYS_PROP_MAXSELECTED)THEN
2944
2945 v_return(i) := TO_CHAR(glMaximumSel(optionIndex));
2946 ListType := DATA_TYPE_INTEGER;
2947
2948 ELSIF(sysPropName = RULE_SYS_PROP_MININSTANCE)THEN
2949
2950 IF(v_tExprSubtype(j) = 53)THEN
2951
2952 --For MinInstances and MaxInstances this is a fix for the bug #3558753.
2953
2954 --The reason we put two sets of MinInstances/MaxInstances was to support backward compatibility
2955 --of rules using those properties in the LHS. 53 and 54 are not mutable, thus they should not
2956 --be on the RHS (generic validation using the view already takes care of that). The remaining
2957 --part is to hard-code generating '0' for 53 (MinInstances) and '1' for 54 (MaxINstances).
2958 --(see also bug #4366895).
2959
2960 v_return(i) := '0';
2961 ELSE
2962
2963 v_return(i) := GENERATE_NAME(j, optionId)||'_MIN';
2964 END IF;
2965 ListType := DATA_TYPE_INTEGER;
2966
2967 ELSIF(sysPropName = RULE_SYS_PROP_MAXINSTANCE)THEN
2968
2969 IF(v_tExprSubtype(j) = 54)THEN
2970
2971 v_return(i) := '1';
2972 ELSE
2973
2974 v_return(i) := GENERATE_NAME(j, optionId)||'_MAX';
2975 END IF;
2976 ListType := DATA_TYPE_INTEGER;
2977
2978 ELSIF(sysPropName = RULE_SYS_PROP_STATE)THEN
2979
2980 v_return(i) := GENERATE_NAME(j, optionId);
2981 ListType := DATA_TYPE_BOOLEAN;
2982
2983 ELSIF(sysPropName = RULE_SYS_PROP_VALUE)THEN
2984
2985 v_return(i) := GENERATE_NAME(j, optionId);
2986 ListType := DATA_TYPE_VOID;
2987
2988 ELSIF(sysPropName = RULE_SYS_PROP_QUANTITY)THEN
2989
2990 v_return(i) := GENERATE_NAME(j, optionId);
2991 ListType := DATA_TYPE_INTEGER;
2992
2993 ELSIF(sysPropName = RULE_SYS_PROP_INSTANCECOUNT)THEN
2994
2995 IF(glPsNodeType(optionIndex) IN (PS_NODE_TYPE_COMPONENT,
2996 PS_NODE_TYPE_REFERENCE,
2997 PS_NODE_TYPE_PRODUCT))THEN
2998
2999 --If it is a non-virtual component/product/reference, we add _ACTUALCOUNT to the name.
3000 --If it is a virtual component/product/reference, we return '1'.
3001 --If it is an option, we just generate the name.
3002
3003 IF(glVirtualFlag(optionIndex) = FLAG_NON_VIRTUAL)THEN
3004 v_return(i) := GENERATE_NAME(j, optionId)||'_ACTUALCOUNT';
3005 ELSE
3006 v_return(i) := '1';
3007 END IF;
3008 ELSE
3009 v_return(i) := GENERATE_NAME(j, optionId);
3010 END IF;
3011
3012 ListType := DATA_TYPE_INTEGER;
3013 ELSE
3014
3015 RAISE CZ_E_NO_SUCH_PROPERTY;
3016 END IF;
3017 ELSE
3018
3019 BEGIN
3020
3021 itemId := glItemId(optionIndex);
3022
3023 v_return(i) := GET_PROPERTY_VALUE(optionId, propertyId, itemId, ListType);
3024
3025 IF(v_return(i) IS NULL)THEN RAISE CZ_E_NULL_PROPERTY_VALUE; END IF;
3026
3027 IF(ListType IN (DATA_TYPE_INTEGER, DATA_TYPE_DECIMAL))THEN
3028
3029 BEGIN
3030 nChild := TO_NUMBER(v_return(i));
3031 EXCEPTION
3032 WHEN OTHERS THEN
3033
3034 SELECT name INTO errorMessage
3035 FROM cz_properties
3036 WHERE property_id = propertyId;
3037
3038 localString := v_return(i);
3039 RAISE CZ_R_INCORRECT_DATA_TYPE;
3040 END;
3041 END IF;
3042
3043 EXCEPTION
3044 WHEN NO_DATA_FOUND THEN
3045 RAISE CZ_E_NO_SUCH_PROPERTY;
3046 WHEN TOO_MANY_ROWS THEN
3047 RAISE CZ_E_INCORRECT_PROPERTY;
3048 WHEN OTHERS THEN
3049 RAISE;
3050 END;
3051 END IF;
3052 END LOOP;
3053
3054 nDebug := 9001009;
3055
3056 RETURN v_return;
3057 END;
3058 ---------------------------------------------------------------------------------------
3059 FUNCTION GENERATE_PROPERTY(j IN PLS_INTEGER) RETURN tStringArray IS
3060 v_return tStringArray;
3061 ListType PLS_INTEGER;
3062 BEGIN
3063
3064 v_return(1) := PROPERTY_VALUE(j, glIndexByPsNodeId(v_tExprPsNodeId(j)), ListType);
3065 RETURN v_return;
3066 END;
3067 ---------------------------------------------------------------------------------------
3068 FUNCTION EXPAND_NODE_OPTIONAL(pvPsNodeId IN NUMBER) RETURN tIntegerArray IS --kdande; Bug 6881902; 11-Mar-2008
3069 v_return tIntegerArray;
3070 nCount PLS_INTEGER;
3071 nStartIndex PLS_INTEGER;
3072 nEndIndex PLS_INTEGER;
3073 indicator PLS_INTEGER := 0;
3074 BEGIN
3075
3076 nStartIndex := glIndexByPsNodeId(pvPsNodeId) + 1;
3077
3078 IF(NOT glLastChildIndex.EXISTS(pvPsNodeId))THEN
3079 localString := glName(glIndexByPsNodeId(pvPsNodeId));
3080 RAISE CZ_E_NO_EXPECTED_CHILDREN;
3081 END IF;
3082
3083 nEndIndex := glLastChildIndex(pvPsNodeId);
3084 nCount := 1;
3085
3086 IF(glPsNodeType(glIndexByPsNodeId(pvPsNodeId)) = PS_NODE_TYPE_FEATURE)THEN
3087
3088 indicator := 1;
3089 FOR i IN nStartIndex..nEndIndex LOOP
3090
3091 v_return(nCount) := i;
3092 nCount := nCount + 1;
3093
3094 END LOOP;
3095 ELSE
3096
3097 FOR i IN nStartIndex..nEndIndex LOOP
3098
3099 IF(glParentId(i) = pvPsNodeId AND glBomRequired(i) = FLAG_BOM_OPTIONAL)THEN
3100
3101 v_return(nCount) := i;
3102 nCount := nCount + 1;
3103
3104 END IF;
3105 END LOOP;
3106 END IF;
3107
3108 --Validate that there are any optional children, otherwise the rule has no sense so
3109 --just ignore it.
3110
3111 IF(v_return.COUNT = 0)THEN
3112 localString := glName(glIndexByPsNodeId(pvPsNodeId));
3113 IF(indicator = 1)THEN
3114 RAISE CZ_E_NO_EXPECTED_CHILDREN;
3115 END IF;
3116 RAISE CZ_E_NO_OPTIONAL_CHILDREN;
3117 END IF;
3118
3119 RETURN v_return;
3120 END;
3121 ---------------------------------------------------------------------------------------
3122 FUNCTION GENERATE_VAL(j IN PLS_INTEGER) RETURN tStringArray IS
3123 v_return tStringArray;
3124 nChild PLS_INTEGER;
3125 ListType PLS_INTEGER;
3126 nCheck NUMBER;
3127 BEGIN
3128
3129 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
3130 RAISE CZ_E_WRONG_VAL_EXPRESSION;
3131 END IF;
3132
3133 nChild := v_ChildrenIndex(v_tExprId(j));
3134 IF(v_tExprParentId.EXISTS(nChild + 1) AND v_tExprParentId(nChild + 1) = v_tExprId(j))THEN
3135 RAISE CZ_E_WRONG_VAL_EXPRESSION;
3136 END IF;
3137
3138 v_return := GENERATE_EXPRESSION(nChild, ListType);
3139
3140 BEGIN
3141 nCheck := TO_NUMBER(v_return(1));
3142 EXCEPTION
3143 WHEN OTHERS THEN
3144 RAISE CZ_E_WRONG_VAL_EXPRESS_TYPE;
3145 END;
3146
3147 RETURN v_return;
3148 END;
3149 ---------------------------------------------------------------------------------------
3150 FUNCTION GENERATE_LOGIC_SIDE(j IN PLS_INTEGER, Operator OUT NOCOPY PLS_INTEGER)
3151 RETURN tStringArray IS
3152 v_return tStringArray;
3153 ListType PLS_INTEGER := NEVER_EXISTS_ID;
3154 BEGIN
3155
3156 nDebug := 8001110;
3157
3158 --Removing the 'simple expression' branch as a part of the fix for the bug #3371279.
3159
3160 IF(v_tExprType(j) = EXPR_OPERATOR AND NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
3161
3162 RAISE CZ_R_INCOMPLETE_LOGIC_RULE;
3163 END IF;
3164
3165 v_return := GENERATE_EXPRESSION(j, ListType);
3166 Operator := OPERATOR_ALLOF;
3167 IF(ListType IN (OPERATOR_ANYOF, OPERATOR_ALLOF))THEN
3168 Operator := ListType;
3169 END IF;
3170 RETURN v_return;
3171 END;
3172 ---------------------------------------------------------------------------------------
3173 PROCEDURE GENERATE_LOGIC_RULE IS
3174 defaultName tStringArray;
3175 itemName tStringArray;
3176 v_lefts tStringArray;
3177 v_rights tStringArray;
3178 LeftOp PLS_INTEGER;
3179 RightOp PLS_INTEGER;
3180 ListType PLS_INTEGER;
3181 ObjectName VARCHAR2(16);
3182 BEGIN
3183
3184 IF(jAntecedentRoot IS NULL OR jConsequentRoot IS NULL)THEN
3185 RAISE CZ_R_INVALID_LOGIC_RULE;
3186 END IF;
3187
3188 nDebug := 8001100;
3189
3190 IF(nRuleOperator = RULE_OPERATOR_DEFAULTS)THEN
3191
3192 nDebug := 8001101;
3193
3194 defaultName := GENERATE_EXPRESSION(jAntecedentRoot, ListType);
3195 ListType := NEVER_EXISTS_ID;
3196 itemName := GENERATE_EXPRESSION(jConsequentRoot, ListType);
3197 IF(ListType NOT IN (OPERATOR_ANYOF, OPERATOR_ALLOF))THEN
3198 ListType := OPERATOR_ANYOF;
3199 END IF;
3200
3201 nDebug := 8001102;
3202
3203 localString := NULL;
3204 IF(itemName.COUNT > 1)THEN localString := sUnsatisfiedId; END IF;
3205
3206 nLocalDefaults := nLocalDefaults + 1;
3207 ObjectName := 'D_' || TO_CHAR(nLocalDefaults) || '_' || TO_CHAR(MaxDepthId);
3208
3209 vLogicLine := 'OBJECT ' || ObjectName || NewLine ||
3210 'WITH _default = ' || defaultName(1) || NewLine ||
3211 'GS R ' || localString || '... ' || TO_CHAR(nReasonId) || NewLine ||
3212 'GL' || OperatorLetters(ListType);
3213
3214 PACK;
3215
3216 nDebug := 8001103;
3217
3218 FOR i IN 1..itemName.COUNT LOOP
3219
3220 vLogicLine := itemName(i) || ' ';
3221 PACK;
3222
3223 END LOOP;
3224
3225 vLogicLine := NewLine || 'GR N ' || ObjectName || NewLine;
3226 PACK;
3227
3228 nDebug := 8001104;
3229
3230 ELSE
3231
3232 nDebug := 8001105;
3233
3234 v_lefts := GENERATE_LOGIC_SIDE(jAntecedentRoot, LeftOp);
3235 v_rights := GENERATE_LOGIC_SIDE(jConsequentRoot, RightOp);
3236
3237 nDebug := 8001106;
3238
3239 localString := NULL;
3240 IF(v_lefts.COUNT > 1 OR v_rights.COUNT > 1)THEN localString := sUnsatisfiedId; END IF;
3241
3242 vLogicLine := 'GS' || OperatorLetters(nRuleOperator) || localString || '... ' || TO_CHAR(nReasonId) || NewLine ||
3243 'GL' || OperatorLetters(LeftOp);
3244 PACK;
3245
3246 nDebug := 8001107;
3247
3248 FOR i IN 1..v_lefts.COUNT LOOP
3249
3250 vLogicLine := v_lefts(i) || ' ';
3251 PACK;
3252
3253 END LOOP;
3254
3255 nDebug := 8001108;
3256
3257 vLogicLine := NewLine || 'GR' || OperatorLetters(RightOp);
3258 PACK;
3259
3260 FOR i IN 1..v_rights.COUNT LOOP
3261
3262 vLogicLine := v_rights(i) || ' ';
3263 PACK;
3264
3265 END LOOP;
3266
3267 vLogicLine := NewLine;
3268 PACK;
3269
3270 nDebug := 8001109;
3271
3272 END IF;
3273 END;
3274 ---------------------------------------------------------------------------------------
3275 FUNCTION HAS_INTEGER_VALUE(j IN PLS_INTEGER) RETURN PLS_INTEGER IS
3276 NodeType PLS_INTEGER := v_tExprType(j);
3277 FeatureType PLS_INTEGER;
3278 SysPropType PLS_INTEGER;
3279 PsNodeIndex PLS_INTEGER;
3280 BEGIN
3281
3282 IF(NodeType = EXPR_ARGUMENT)THEN
3283
3284 PsNodeIndex := LOOKUP_ARGUMENT(j);
3285 IF(parameterScope(PsNodeIndex).node_id IS NULL)THEN RETURN GENERATE_SCOPE_ERROR; END IF;
3286
3287 NodeType := EXPR_PSNODE;
3288 v_tExprPsNodeId(j) := parameterScope(PsNodeIndex).node_id;
3289 END IF;
3290
3291 IF(NodeType = EXPR_PSNODE)THEN
3292
3293 NodeType := glPsNodeType(glIndexByPsNodeId(v_tExprPsNodeId(j)));
3294 FeatureType := glFeatureType(glIndexByPsNodeId(v_tExprPsNodeId(j)));
3295 localString := glName(glIndexByPsNodeId(v_tExprPsNodeId(j)));
3296
3297 IF(NodeType = PS_NODE_TYPE_FEATURE AND FeatureType IN
3298 (PS_NODE_FEATURE_TYPE_OPTION, PS_NODE_FEATURE_TYPE_BOOLEAN)
3299 AND (NOT v_ChildrenIndex.EXISTS(v_tExprId(j))))THEN
3300
3301 IF(FeatureType = PS_NODE_FEATURE_TYPE_OPTION)THEN
3302 errorMessage := 'Option Feature';
3303 ELSE
3304 errorMessage := 'Boolean Feature';
3305 END IF;
3306 RAISE CZ_R_INCORRECT_NUMERIC_RHS;
3307 ELSIF(NodeType = PS_NODE_TYPE_COMPONENT AND (NOT v_ChildrenIndex.EXISTS(v_tExprId(j))))THEN
3308
3309 --Bug #3800339. This is a component without a system property applied. As the data is corrupted,
3310 --it may not be possible to catch things like that by queries against the seed data.
3311
3312 errorMessage := 'Component';
3313 RAISE CZ_R_INCORRECT_NUMERIC_RHS;
3314 END IF;
3315
3316 IF(v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
3317 IF(v_tExprType(v_ChildrenIndex(v_tExprId(j))) = EXPR_PROP)THEN
3318
3319 --User properties are not allowed in the consequent expression.
3320
3321 RAISE CZ_R_INVALID_NUMERIC_RULE;
3322 END IF;
3323
3324 SysPropType := v_tExprSubtype(v_ChildrenIndex(v_tExprId(j)));
3325 IF(NOT h_SeededName.EXISTS(SysPropType))THEN RAISE CZ_E_BAD_PROPERTY_TYPE; END IF;
3326
3327 IF(h_SeededName(SysPropType) = RULE_SYS_PROP_SELECTION)THEN RETURN GENERATE_DYNAMIC; END IF;
3328
3329 IF(h_SeededName(SysPropType) <> RULE_SYS_PROP_SELECTION AND
3330 (NOT APPLICABLE_SYS_PROP(j, NULL, SysPropType)))THEN
3331
3332 localString := h_ReportName(sysPropType);
3333 auxIndex := glIndexByPsNodeId(v_tExprPsNodeId(j));
3334 RAISE CZ_R_INCOMPATIBLE_SYSPROP;
3335 ELSE
3336
3337 --Bug #4677027. No rounding operator for contributions to any bom nodes.
3338
3339 IF(NodeType IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN RETURN GENERATE_CONTRIBUTE; END IF;
3340
3341 IF(COMPATIBLE_DATA_TYPES(SIGNATURE_DATA_TYPE(h_SignatureId(SysPropType)), DATATYPE_INTEGER))THEN
3342 RETURN GENERATE_INCREMENT;
3343 END IF;
3344 END IF;
3345 ELSE
3346 IF(NodeType = PS_NODE_TYPE_OPTION OR
3347 (NodeType = PS_NODE_TYPE_FEATURE AND FeatureType = PS_NODE_FEATURE_TYPE_INTEGER))THEN
3348 RETURN GENERATE_INCREMENT;
3349 END IF;
3350 END IF;
3351 RETURN GENERATE_CONTRIBUTE;
3352 ELSE
3353 RETURN GENERATE_CONTRIBUTE;
3354 END IF;
3355 END;
3356 ---------------------------------------------------------------------------------------
3357 FUNCTION GENERATE_NUMERIC_PART(j IN PLS_INTEGER, NodeId IN OUT NOCOPY NUMBER) --kdande; Bug 6881902; 11-Mar-2008
3358 RETURN VARCHAR2 IS
3359 ExprType PLS_INTEGER := v_tExprType(j);
3360 v_return VARCHAR2(4000);
3361 v_propval tStringArray;
3362 ListType PLS_INTEGER;
3363 nChild NUMBER;
3364 BEGIN
3365 IF(ExprType IN (EXPR_PSNODE, EXPR_ARGUMENT))THEN
3366
3367 v_propval := GENERATE_EXPRESSION(j, ListType);
3368 v_return := v_propval(1);
3369 NodeId := v_tExprPsNodeId(j);
3370
3371 ELSIF(ExprType = EXPR_NODE_TYPE_COUNT)THEN
3372
3373 v_return := GENERATE_NAME(j, v_tExprPsNodeId(j));
3374 NodeId := v_tExprPsNodeId(j);
3375
3376 ELSIF(ExprType = EXPR_NODE_TYPE_LITERAL)THEN
3377
3378 v_return := v_tExprDataValue(j);
3379 NodeId := 0;
3380
3381 ELSIF(ExprType = EXPR_NODE_TYPE_PROP)THEN
3382
3383 v_return := PROPERTY_VALUE(j, glIndexByPsNodeId(NodeId), ListType);
3384 NodeId := 0;
3385
3386 BEGIN
3387 nChild := TO_NUMBER(v_return);
3388 IF(nChild = 0)THEN NodeId := -1; END IF;
3389 EXCEPTION
3390 WHEN OTHERS THEN
3391
3392 SELECT name INTO errorMessage
3393 FROM cz_properties
3394 WHERE property_id = v_tExprPropertyId(j);
3395
3396 RAISE CZ_R_INCORRECT_NUMERICLHS;
3397 END;
3398
3399 ELSIF(ExprType = EXPR_NODE_TYPE_OPERATOR AND v_tExprSubtype(j) = OPERATOR_DOT)THEN
3400
3401 nChild := v_ChildrenIndex(v_tExprId(j));
3402 v_tExplNodeId(nChild + 1) := v_tExplNodeId(nChild);
3403 v_return := PROPERTY_VALUE(nChild + 1, glIndexByPsNodeId(v_tExprPsNodeId(nChild)), ListType);
3404 NodeId := v_tExprPsNodeId(nChild);
3405
3406 ELSE
3407
3408 RAISE CZ_R_INVALID_NUMERIC_PART;
3409
3410 END IF;
3411 RETURN v_return;
3412 END;
3413 ---------------------------------------------------------------------------------------
3414 FUNCTION GENERATE_BOOLEAN_PART(j IN PLS_INTEGER) RETURN VARCHAR2 IS
3415 nChild PLS_INTEGER;
3416 v_return VARCHAR2(4000);
3417 v_index tIntegerArray;
3418 ExprId PLS_INTEGER := v_tExprId(j);
3419 BEGIN
3420
3421 nDebug := 8001001;
3422
3423 nChild := v_ChildrenIndex(ExprId);
3424
3425 nDebug := 8001002;
3426
3427 nLocalDefaults := nLocalDefaults + 1;
3428 v_return := t_prefix || TO_CHAR(nLocalDefaults);
3429
3430 vLogicLine := 'OBJECT ' || v_return || NewLine ||
3431 'GS R ... ' || TO_CHAR(nReasonId) || NewLine ||
3432 'GL' || OperatorLetters(v_tExprSubtype(j));
3433 PACK;
3434
3435 nDebug := 8001004;
3436
3437 WHILE(v_tExprParentId(nChild) = ExprId) LOOP
3438
3439 v_index := EXPAND_NODE(nChild);
3440
3441 FOR i IN 1..v_index.COUNT LOOP
3442
3443 vLogicLine := GENERATE_NAME_EXPL(v_ExplByPsNodeId(v_index(i)), v_index(i)) || ' ';
3444 PACK;
3445 END LOOP;
3446
3447 nChild := nChild + 1;
3448 END LOOP;
3449
3450 nDebug := 8001005;
3451
3452 vLogicLine := NewLine || 'GR' || OperatorLetters(OPERATOR_ALLOF) || v_return || NewLine;
3453 PACK;
3454
3455 nDebug := 8001006;
3456
3457 RETURN v_return;
3458 END;
3459 ---------------------------------------------------------------------------------------
3460 PROCEDURE GENERATE_INCREMENT_LOGIC IS
3461 v_NodeId NUMBER; --kdande; Bug 6881902; 11-Mar-2008
3462 v_HeaderId NUMBER;
3463 v_return VARCHAR2(4000);
3464 v_result tStringArray;
3465 v_index tStringArray;
3466 v_acname VARCHAR2(4000);
3467 v_nodename VARCHAR2(4000);
3468 v_accuname VARCHAR2(4000);
3469 ListType PLS_INTEGER;
3470 sSign VARCHAR2(8) := NULL;
3471 lhsNode PLS_INTEGER := 0;
3472 rhsNode PLS_INTEGER := 0;
3473 lhsName VARCHAR2(4000);
3474 rhsName VARCHAR2(4000);
3475 nOpNode PLS_INTEGER;
3476 nChild PLS_INTEGER;
3477 nGrandChild PLS_INTEGER;
3478 nSuffix PLS_INTEGER := 0;
3479 iLocal PLS_INTEGER;
3480 operatorLiteral VARCHAR2(4000);
3481 v_name VARCHAR2(128);
3482 ---------------------------------------------------------------------------------------
3483 PROCEDURE GENERATE_INCREMENT_RECORD IS
3484 v_total VARCHAR2(4000) := NULL;
3485 BEGIN
3486
3487 IF(v_tExprSubtype(nOpNode) = OPERATOR_DIV)THEN
3488
3489 v_total := t_prefix || v_name || '_' || TO_CHAR(nSuffix);
3490 vLogicLine := 'TOTAL ' || v_total || NewLine ||
3491 'CONTRIBUTE ' || lhsName || OperatorLiterals(OPERATOR_DIV) ||
3492 rhsName || ' ' || v_total || ' ... ' || TO_CHAR(nReasonId) || NewLine;
3493 PACK;
3494 ELSIF(v_tExprSubtype(nOpNode) = OPERATOR_MATHDIV)THEN
3495
3496 v_total := t_prefix || v_name || '_' || TO_CHAR(nSuffix);
3497 vLogicLine := 'TOTAL ' || v_total || NewLine ||
3498 'MF ' || lhsName || ' ' || rhsName || OperatorLiterals(OPERATOR_MATHDIV) ||
3499 v_total || ' ... ' || TO_CHAR(nReasonId) || NewLine;
3500 PACK;
3501 END IF;
3502
3503 sSign := NULL;
3504 IF(nRuleOperator = RULE_OPERATOR_CONSUMES)THEN
3505 sSign := '-1 ';
3506 END IF;
3507
3508 IF(v_total IS NULL)THEN
3509
3510 vLogicLine := 'INC ' || sSign || lhsName || ' ' || rhsName || ' ' || v_acname ||
3511 OperatorLiteral || '... ' || TO_CHAR(nReasonId) || NewLine;
3512
3513 ELSE
3514
3515 vLogicLine := 'INC ' || sSign || v_total || ' ' || v_acname ||
3516 OperatorLiteral || '... ' || TO_CHAR(nReasonId) || NewLine;
3517
3518 END IF;
3519 PACK;
3520 END;
3521 ---------------------------------------------------------------------------------------
3522 BEGIN
3523
3524 nLocalDefaults := nLocalDefaults + 1;
3525 v_name := TO_CHAR(nLocalDefaults);
3526
3527 --Generate the accumulator and corresponding increment relation if necessary
3528
3529 nDebug := 8001200;
3530
3531 v_return := GENERATE_NUMERIC_PART(jConsequentRoot, v_NodeId);
3532
3533 nDebug := 8001201;
3534
3535 IF(v_tExprType(jConsequentRoot) = EXPR_NODE_TYPE_OPERATOR AND
3536 v_tExprSubtype(jConsequentRoot) = OPERATOR_DOT)THEN
3537
3538 nDebug := 8001202;
3539
3540 nChild := v_ChildrenIndex(v_tExprId(jConsequentRoot)) + 1;
3541 v_acname := v_return;
3542
3543 --Commenting the following block out as the fix to bug #1657701. Assuming that this code
3544 --was necessary until some fixes in participants' model_ref_expl_id population hadn't
3545 --been done, and now it's obsolete.
3546 /*
3547 IF(v_NodeId = v_tPsNodeId(v_IndexByNodeId(MaxDepthId)))THEN
3548 v_acname := PATH_DELIMITER || 'parent' || PATH_DELIMITER || v_acname;
3549 END IF;
3550 */
3551
3552 ELSIF(v_tExprType(jConsequentRoot) = EXPR_PSNODE AND v_ChildrenIndex.EXISTS(v_tExprId(jConsequentRoot)))THEN
3553
3554 nChild := jConsequentRoot;
3555 v_acname := v_return;
3556
3557 ELSIF((NOT v_HeaderByAccId.EXISTS(v_NodeId)) AND
3558 (glAccumulator(v_NodeId) IS NULL OR glAccumulator(v_NodeId) = FLAG_NO_ACCUMULATOR))THEN
3559
3560 nDebug := 8001203;
3561
3562 v_HeaderId := glHeaderByPsNodeId(v_NodeId);
3563 v_nodename := 'P_' || TO_CHAR(glPersistentId(v_NodeId));
3564 v_accuname := v_nodename || '_ACC';
3565
3566 --Flush off the buffer because we are about to write to another file
3567
3568 IF(vLogicText IS NOT NULL)THEN
3569 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
3570 (nHeaderId, v_tSequenceNbr(nHeaderId), vLogicText);
3571 vLogicText := NULL;
3572 v_tSequenceNbr(nHeaderId) := v_tSequenceNbr(nHeaderId) + 1;
3573 END IF;
3574
3575 --Fix for the bug #2398832 - we may be re-using the accumulator, so we should not
3576 --assign to it effectivities and usages of a particular node.
3577 --Do not write the effectivity dates using the actual effective date interval of
3578 --the corresponding node.
3579
3580 --iLocal := glIndexByPsNodeId(v_NodeId);
3581 --CurrentEffFrom := glEffFrom(iLocal);
3582 --CurrentEffUntil := glEffUntil(iLocal);
3583 --CurrentUsageMask := glUsageMask(iLocal);
3584
3585 --Instead make the accumulator always effective and universal.
3586
3587 CurrentEffFrom := EpochBeginDate;
3588 CurrentEffUntil := EpochEndDate;
3589 CurrentUsageMask := AnyUsageMask;
3590
3591 IF((NOT h_EffFrom.EXISTS(v_HeaderId)) OR
3592 (h_EffFrom(v_HeaderId) <> CurrentEffFrom OR h_EffUntil(v_HeaderId) <> CurrentEffUntil OR
3593 h_EffUsageMask(v_HeaderId) <> CurrentUsageMask))THEN
3594
3595 h_EffFrom(v_HeaderId) := CurrentEffFrom;
3596 h_EffUntil(v_HeaderId) := CurrentEffUntil;
3597 h_EffUsageMask(v_HeaderId) := CurrentUsageMask;
3598
3599 vLogicText := LTRIM(CurrentUsageMask, '0');
3600 IF(vLogicText IS NOT NULL) THEN
3601 vLogicText := EffUsagePrefix || vLogicText;
3602 END IF;
3603
3604 IF(CurrentEffFrom = EpochBeginDate)THEN
3605 CurrentFromDate := NULL;
3606 ELSE
3607 CurrentFromDate := TO_CHAR(CurrentEffFrom, EffDateFormat);
3608 END IF;
3609
3610 IF(CurrentEffUntil = EpochEndDate)THEN
3611 CurrentUntilDate := NULL;
3612 ELSE
3613 CurrentUntilDate := TO_CHAR(CurrentEffUntil, EffDateFormat);
3614 END IF;
3615
3616 vLogicText := 'EFF ' || CurrentFromDate || ', ' || CurrentUntilDate || ', ' || vLogicText || NewLine;
3617 END IF;
3618
3619 vLogicText := vLogicText || 'TOTAL ' || v_accuname || NewLine ||
3620 'INC ' || v_accuname || ' ' || v_nodename ||
3621 OperatorLiterals(OPERATOR_ROUND) || '... ' || TO_CHAR(nReasonId) || NewLine;
3622
3623 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
3624 (v_HeaderId, vSeqNbrByHeader(v_HeaderId), vLogicText);
3625 vLogicText := NULL;
3626 vSeqNbrByHeader(v_HeaderId) := vSeqNbrByHeader(v_HeaderId) + 1;
3627
3628 v_HeaderByAccId(v_NodeId) := v_HeaderId;
3629 v_acname := v_return || '_ACC';
3630
3631 --Part of the fix for the bug #2857955. We will never be here if glAccumulator(v_NodeId) was
3632 --FLAG_ACCUMULATOR_ACC because the accumulator would have already been created.
3633
3634 UPDATE cz_ps_nodes SET
3635 accumulator_flag = DECODE(glAccumulator(v_NodeId), FLAG_ACCUMULATOR_NT, FLAG_ACCUMULATOR_BOTH, FLAG_ACCUMULATOR_ACC)
3636 WHERE ps_node_id = v_NodeId;
3637
3638 ELSE
3639
3640 nDebug := 8001204;
3641
3642 v_acname := v_return || '_ACC';
3643 END IF;
3644
3645 nDebug := 8001205;
3646
3647 --If we are here, than the RHS expression has an integer value and so the LHS expression
3648 --should have a root rounding operator. So go down one level.
3649 --However, as a fix for the bug #3558699 we now don't require the root rounding operator
3650 --if the data type of antecedent is convertible to integer. Therefore we have to be more
3651 --flexible here.
3652
3653 IF(v_tExprType(jAntecedentRoot) <> EXPR_OPERATOR OR v_tExprSubtype(jAntecedentRoot) NOT IN
3654 (OPERATOR_ROUND, OPERATOR_CEILING, OPERATOR_FLOOR, OPERATOR_TRUNCATE, OPERATOR_NONE))THEN
3655 nOpNode := jAntecedentRoot;
3656 OperatorLiteral := OperatorLiterals(OPERATOR_NONE);
3657 ELSE
3658 nOpNode := v_ChildrenIndex(v_tExprId(jAntecedentRoot));
3659 OperatorLiteral := OperatorLiterals(v_tExprSubtype(jAntecedentRoot));
3660 END IF;
3661
3662 IF(v_tExprType(nOpNode) = EXPR_OPERATOR AND (NOT v_ChildrenIndex.EXISTS(v_tExprId(nOpNode))))THEN
3663 RAISE CZ_R_INCOMPLETE_NUMERIC_RULE;
3664 END IF;
3665
3666 IF(v_ChildrenIndex.EXISTS(v_tExprId(nOpNode)))THEN
3667 lhsNode := v_ChildrenIndex(v_tExprId(nOpNode));
3668 rhsNode := lhsNode + v_NumberOfChildren(v_tExprId(nOpNode)) - 1;
3669 END IF;
3670
3671 IF(nPresentationFlag = FLAG_FREEFORM_RULE)THEN
3672
3673 --Check if this is a simple numeric rule that has been upgraded to become a free-form rule. For such
3674 --rules we want to generate an optimized INC relation.
3675 --Bug #4047086. However, the operator can only be multiplication to be able to optimize.
3676 --Bugs #4256960, #4254591. The RHS operand must also be simple, not an operator.
3677
3678 IF((v_tExprType(nOpNode) = EXPR_OPERATOR AND v_tExprSubtype(nOpNode) = OPERATOR_MULT) AND
3679 (v_tExprType(rhsNode) <> EXPR_OPERATOR) AND (v_tExprType(lhsNode) = EXPR_LITERAL OR
3680 (v_tExprType(lhsNode) IN (EXPR_PSNODE, EXPR_ARGUMENT) AND (NOT HAS_OPTIONS_APPLIED(lhsNode)))))THEN
3681
3682 rhsNode := lhsNode + 1;
3683
3684 lhsName := GENERATE_NUMERIC_PART(lhsNode, v_NodeId);
3685 rhsName := GENERATE_NUMERIC_PART(rhsNode, v_NodeId);
3686 GENERATE_INCREMENT_RECORD;
3687 RETURN;
3688 ELSE
3689
3690 nDebug := 8001206;
3691
3692 numericLHS := 1;
3693 v_result := GENERATE_EXPRESSION(nOpNode, ListType);
3694 IF(nRuleOperator = RULE_OPERATOR_CONSUMES)THEN
3695 sSign := '-1 ';
3696 END IF;
3697 vLogicLine := 'INC ' || sSign || v_result(1) || ' ' || v_acname ||
3698 OperatorLiteral || '... ' || TO_CHAR(nReasonId) || NewLine;
3699 PACK;
3700 RETURN;
3701 END IF;
3702 END IF;
3703
3704 nDebug := 8001207;
3705
3706 FOR i IN lhsNode..rhsNode - 1 LOOP
3707 IF(v_tExprType(i) = EXPR_PSNODE AND HAS_OPTIONS_APPLIED(i))THEN
3708
3709 v_index := GENERATE_CHILDRENOF(v_tExplNodeId(i), v_tExprPsNodeId(i));
3710
3711 FOR ich IN 1..v_index.COUNT LOOP
3712
3713 lhsName := v_index(ich);
3714 rhsName := GENERATE_NUMERIC_PART(rhsNode, v_NodeId);
3715 GENERATE_INCREMENT_RECORD;
3716 nSuffix := nSuffix + 1;
3717 END LOOP;
3718 ELSIF(v_tExprType(i) IN (EXPR_LITERAL, EXPR_PSNODE))THEN
3719
3720 lhsName := GENERATE_NUMERIC_PART(i, v_NodeId);
3721 v_NodeId := v_tExprPsNodeId(i);
3722 rhsName := GENERATE_NUMERIC_PART(rhsNode, v_NodeId);
3723
3724 GENERATE_INCREMENT_RECORD;
3725 nSuffix := nSuffix + 1;
3726 ELSE
3727
3728 RAISE CZ_R_INVALID_NUMRULE_NODE;
3729 END IF;
3730 END LOOP;
3731 END;
3732 ---------------------------------------------------------------------------------------
3733 PROCEDURE GENERATE_CONTRIBUTE_LOGIC IS
3734 v_return VARCHAR2(4000);
3735 v_result tStringArray;
3736 v_index tStringArray;
3737 ListType PLS_INTEGER;
3738 sSign VARCHAR2(8);
3739 lhsNode PLS_INTEGER;
3740 rhsNode PLS_INTEGER;
3741 lhsName VARCHAR2(4000);
3742 rhsName VARCHAR2(4000);
3743 nChild PLS_INTEGER;
3744 nGrandChild PLS_INTEGER;
3745 v_NodeId NUMBER; --kdande; Bug 6881902; 11-Mar-2008
3746 nSuffix PLS_INTEGER := 0;
3747 nOpNode PLS_INTEGER := jAntecedentRoot;
3748 sOpRoot VARCHAR2(16):= ' ';
3749 v_HeaderId NUMBER;
3750 v_nodename VARCHAR2(4000);
3751 v_accuname VARCHAR2(4000);
3752 iLocal PLS_INTEGER;
3753 v_name VARCHAR2(128);
3754 ---------------------------------------------------------------------------------------
3755 PROCEDURE GENERATE_CONTRIBUTE_RECORD IS
3756 v_total VARCHAR2(4000);
3757 v_local VARCHAR2(4000) := v_return;
3758 BEGIN
3759 IF(nRuleOperator = RULE_OPERATOR_CONSUMES)THEN
3760
3761 v_total := t_prefix || v_name || '_' || TO_CHAR(nSuffix);
3762 vLogicLine := 'TOTAL ' || v_total || NewLine ||
3763 'CONTRIBUTE ' || v_total || OperatorLiterals(OPERATOR_MULT) ||
3764 '-1 ' || v_local || ' ... ' || TO_CHAR(nReasonId) || NewLine;
3765 v_local := v_total;
3766 PACK;
3767 END IF;
3768
3769 IF(v_NodeId = -1 AND v_tExprSubtype(nOpNode) = OPERATOR_MULT)THEN
3770
3771 vLogicLine := 'CONTRIBUTE ' || lhsName || OperatorLiterals(OPERATOR_SUB) ||
3772 lhsName || ' ' || v_local || sOpRoot || '... ' || TO_CHAR(nReasonId) || NewLine;
3773 ELSIF(v_tExprSubtype(nOpNode) = OPERATOR_MATHDIV)THEN
3774
3775 v_total := t_prefix || v_name || '_' || TO_CHAR(nSuffix);
3776 vLogicLine := 'TOTAL ' || v_total || NewLine ||
3777 'MF ' || lhsName || ' ' || rhsName || OperatorLiterals(OPERATOR_MATHDIV) ||
3778 v_total || ' ... ' || TO_CHAR(nReasonId) || NewLine;
3779 PACK;
3780 vLogicLine := 'CONTRIBUTE 1 ' || v_total || ' ' || v_local || sOpRoot || '... ' || TO_CHAR(nReasonId) || NewLine;
3781 ELSE
3782
3783 vLogicLine := 'CONTRIBUTE ' || lhsName || OperatorLiterals(v_tExprSubtype(nOpNode)) ||
3784 rhsName || ' ' || v_local || sOpRoot || '... ' || TO_CHAR(nReasonId) || NewLine;
3785 END IF;
3786 PACK;
3787 END;
3788 ---------------------------------------------------------------------------------------
3789 BEGIN
3790
3791 nLocalDefaults := nLocalDefaults + 1;
3792 v_name := TO_CHAR(nLocalDefaults);
3793
3794 nDebug := 8002;
3795
3796 v_return := GENERATE_NUMERIC_PART(jConsequentRoot, v_NodeId);
3797 optimizeChain := OPTIMIZATION_UNKNOWN;
3798 optimizeContribute := OPTIMIZATION_UNKNOWN;
3799
3800 IF(v_tLogicNetType(nHeaderId) = LOGIC_NET_TYPE_NETWORK AND
3801 glPsNodeType(glIndexByPsNodeId(v_NodeId)) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
3802
3803 --This is a conditional numeric rule against a BOM node. We will create an accumulator and
3804 --a 'contribute' relation from the accumulator to the BOM object, if such accumulator does
3805 --not exist. We'll need to temporarily switch context to the BOM object's structure file.
3806
3807 IF((NOT v_HeaderByAccId.EXISTS(v_NodeId)) AND
3808 (glAccumulator(v_NodeId) IS NULL OR glAccumulator(v_NodeId) = FLAG_NO_ACCUMULATOR))THEN
3809
3810 --Retrieve the corresponding structure file header and prepare the names.
3811
3812 v_HeaderId := glHeaderByPsNodeId(v_NodeId);
3813 v_nodename := 'P_' || TO_CHAR(glPersistentId(v_NodeId));
3814 v_accuname := v_nodename || '_ACC';
3815
3816 --Flush off the buffer because we are about to write to another file.
3817
3818 IF(vLogicText IS NOT NULL)THEN
3819 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
3820 (nHeaderId, v_tSequenceNbr(nHeaderId), vLogicText);
3821 vLogicText := NULL;
3822 v_tSequenceNbr(nHeaderId) := v_tSequenceNbr(nHeaderId) + 1;
3823 END IF;
3824
3825 --Fix for the bug #2398832 - we may be re-using the accumulator, so we should not
3826 --assign to it effectivities and usages of a particular node.
3827 --Do not write the effectivity dates using the actual effective date interval of
3828 --the corresponding node.
3829
3830 --iLocal := glIndexByPsNodeId(v_NodeId);
3831 --CurrentEffFrom := glEffFrom(iLocal);
3832 --CurrentEffUntil := glEffUntil(iLocal);
3833 --CurrentUsageMask := glUsageMask(iLocal);
3834
3835 --Instead make the accumulator always effective and universal.
3836
3837 CurrentEffFrom := EpochBeginDate;
3838 CurrentEffUntil := EpochEndDate;
3839 CurrentUsageMask := '0';
3840
3841 IF((NOT h_EffFrom.EXISTS(v_HeaderId)) OR
3842 (h_EffFrom(v_HeaderId) <> CurrentEffFrom OR h_EffUntil(v_HeaderId) <> CurrentEffUntil OR
3843 h_EffUsageMask(v_HeaderId) <> CurrentUsageMask))THEN
3844
3845 h_EffFrom(v_HeaderId) := CurrentEffFrom;
3846 h_EffUntil(v_HeaderId) := CurrentEffUntil;
3847 h_EffUsageMask(v_HeaderId) := CurrentUsageMask;
3848
3849 vLogicText := LTRIM(CurrentUsageMask, '0');
3850 IF(vLogicText IS NOT NULL) THEN
3851 vLogicText := EffUsagePrefix || vLogicText;
3852 END IF;
3853
3854 IF(CurrentEffFrom = EpochBeginDate)THEN
3855 CurrentFromDate := NULL;
3856 ELSE
3857 CurrentFromDate := TO_CHAR(CurrentEffFrom, EffDateFormat);
3858 END IF;
3859
3860 IF(CurrentEffUntil = EpochEndDate)THEN
3861 CurrentUntilDate := NULL;
3862 ELSE
3863 CurrentUntilDate := TO_CHAR(CurrentEffUntil, EffDateFormat);
3864 END IF;
3865
3866 vLogicText := 'EFF ' || CurrentFromDate || ', ' || CurrentUntilDate || ', ' || vLogicText || NewLine;
3867 END IF;
3868
3869 --Write the logic record in the structure file.
3870
3871 vLogicText := vLogicText || 'TOTAL ' || v_accuname || NewLine ||
3872 'CONTRIBUTE 1 ' || v_accuname || ' ' || v_nodename ||
3873 ' ... ' || TO_CHAR(nReasonId) || NewLine;
3874
3875 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
3876 (v_HeaderId, vSeqNbrByHeader(v_HeaderId), vLogicText);
3877
3878 vLogicText := NULL;
3879 vSeqNbrByHeader(v_HeaderId) := vSeqNbrByHeader(v_HeaderId) + 1;
3880 v_HeaderByAccId(v_NodeId) := v_HeaderId;
3881
3882 --This line and the ELSE branch below are to fix the bug #2702587 - we need not only create the
3883 --accumulator and a relation for it to the object but we also need to generate the rule so that
3884 --it contributes to the accumulator, not the objects.
3885
3886 v_return := v_return || '_ACC';
3887
3888 --Part of the fix for the bug #2857955. We will never be here if glAccumulator(v_NodeId) was
3889 --FLAG_ACCUMULATOR_ACC because the accumulator would have already been created.
3890
3891 UPDATE cz_ps_nodes SET
3892 accumulator_flag = DECODE(glAccumulator(v_NodeId), FLAG_ACCUMULATOR_NT, FLAG_ACCUMULATOR_BOTH, FLAG_ACCUMULATOR_ACC)
3893 WHERE ps_node_id = v_NodeId;
3894
3895 ELSE
3896
3897 v_return := v_return || '_ACC';
3898 END IF;
3899 END IF;
3900
3901 nDebug := 8003;
3902
3903 IF(v_tExprSubtype(jAntecedentRoot) IN
3904 (OPERATOR_ROUND, OPERATOR_FLOOR, OPERATOR_CEILING, OPERATOR_TRUNCATE, OPERATOR_NONE))THEN
3905 nOpNode := v_ChildrenIndex(v_tExprId(jAntecedentRoot));
3906 sOpRoot := OperatorLiterals(v_tExprSubtype(jAntecedentRoot));
3907 END IF;
3908
3909 IF(nPresentationFlag = FLAG_FREEFORM_RULE)THEN
3910
3911 nDebug := 8004;
3912
3913 IF(nRuleOperator = RULE_OPERATOR_CONTRIBUTES)THEN
3914
3915 sSign := '1 ';
3916
3917 --If this is a numeric contribute rule with a root rounding operator, set the flag and store
3918 --the target from the Motorola optimization (bug #2540163).
3919
3920 IF(v_tExprSubtype(jAntecedentRoot) IN
3921 (OPERATOR_ROUND, OPERATOR_FLOOR, OPERATOR_CEILING, OPERATOR_TRUNCATE))THEN
3922
3923 optimizeChain := OPTIMIZATION_REQUESTED;
3924 optimizeTarget := v_return;
3925 ELSE
3926
3927 optimizeContribute := OPTIMIZATION_REQUESTED;
3928 END IF;
3929 ELSE
3930
3931 sSign := '-1 ';
3932 END IF;
3933
3934 nDebug := 8004001;
3935
3936 numericLHS := 1;
3937 v_result := GENERATE_EXPRESSION(jAntecedentRoot, ListType);
3938
3939 --The value may have been changed during the expression generation. If it is not 0, we still
3940 --want to generate the rule's contribute relation. However, if it is 0 than the relation has
3941 --already been generated as a part of the optimization so here we just skip it.
3942
3943 IF(optimizeChain IN (OPTIMIZATION_REQUESTED, OPTIMIZATION_UNKNOWN))THEN
3944 IF(optimizeContribute = OPTIMIZATION_COMPLETED)THEN
3945
3946 vLogicLine := 'CONTRIBUTE ' || v_result(1) || v_return || ' ... ' || TO_CHAR(nReasonId) || NewLine;
3947 ELSE
3948
3949 vLogicLine := 'CONTRIBUTE ' || v_result(1) || OperatorLiterals(OPERATOR_MULT) ||
3950 sSign || v_return || sOpRoot || '... ' || TO_CHAR(nReasonId) || NewLine;
3951 END IF;
3952
3953 PACK;
3954 optimizeChain := OPTIMIZATION_UNKNOWN;
3955 END IF;
3956
3957 RETURN;
3958 END IF;
3959
3960 nDebug := 8005;
3961
3962 lhsNode := v_ChildrenIndex(v_tExprId(nOpNode));
3963 rhsNode := lhsNode + v_NumberOfChildren(v_tExprId(nOpNode)) - 1;
3964
3965 nDebug := 8006;
3966
3967 FOR i IN lhsNode..rhsNode - 1 LOOP
3968
3969 IF(v_tExprType(i) = EXPR_PSNODE AND HAS_OPTIONS_APPLIED(i))THEN
3970
3971 v_index := GENERATE_CHILDRENOF(v_tExplNodeId(i), v_tExprPsNodeId(i));
3972
3973 FOR ich IN 1..v_index.COUNT LOOP
3974
3975 lhsName := v_index(ich);
3976 rhsName := GENERATE_NUMERIC_PART(rhsNode, v_NodeId);
3977
3978 GENERATE_CONTRIBUTE_RECORD;
3979 nSuffix := nSuffix + 1;
3980 END LOOP;
3981 ELSIF(v_tExprType(i) IN (EXPR_LITERAL, EXPR_PSNODE))THEN
3982
3983 lhsName := GENERATE_NUMERIC_PART(i, v_NodeId);
3984 v_NodeId := v_tExprPsNodeId(i);
3985 rhsName := GENERATE_NUMERIC_PART(rhsNode, v_NodeId);
3986
3987 GENERATE_CONTRIBUTE_RECORD;
3988 nSuffix := nSuffix + 1;
3989 ELSE
3990
3991 RAISE CZ_R_INVALID_NUMRULE_NODE;
3992 END IF;
3993 END LOOP;
3994 END;
3995 ---------------------------------------------------------------------------------------
3996 PROCEDURE GENERATE_DYNAMIC_LOGIC IS
3997 v_result tStringArray;
3998 v_children tIntegerArray;
3999 ListType PLS_INTEGER;
4000 v_name VARCHAR2(4000);
4001 v_return VARCHAR2(4000);
4002 v_object VARCHAR2(4000);
4003 v_index PLS_INTEGER;
4004 BEGIN
4005
4006 IF(v_tExprType(jConsequentRoot) = EXPR_ARGUMENT)THEN
4007
4008 ListType := DATA_TYPE_NODE;
4009 v_result := GENERATE_ARGUMENT(jConsequentRoot, ListType);
4010 END IF;
4011
4012 nLocalDefaults := nLocalDefaults + 1;
4013 v_return := t_prefix || TO_CHAR(nLocalDefaults);
4014 v_index := 1;
4015
4016 v_result.DELETE;
4017 v_result := GENERATE_EXPRESSION(jAntecedentRoot, ListType);
4018 v_children := EXPAND_NODE_OPTIONAL(v_tExprPsNodeId(jConsequentRoot));
4019
4020 FOR i IN 1..v_result.COUNT LOOP
4021 FOR ii IN 1..v_children.COUNT LOOP
4022
4023 v_name := GENERATE_NAME_EXPL(v_tExplNodeId(jConsequentRoot), glPsNodeId(v_children(ii)));
4024 v_object := v_return || '_' || TO_CHAR(v_index);
4025
4026 vLogicLine := 'OBJECT ' || v_object || NewLine ||
4027 'GS I ... ' || TO_CHAR(nReasonId) || NewLine ||
4028 'GL' || OperatorLetters(OPERATOR_ALLOF) || v_name || NewLine ||
4029 'GR' || OperatorLetters(OPERATOR_ALLOF) || v_object || NewLine ||
4030 'INC ' || v_result(i) || ' ' || v_object || ' ' || v_name ||
4031 ' ... ' || TO_CHAR(nReasonId) || NewLine;
4032 PACK;
4033
4034 v_index := v_index + 1;
4035 END LOOP;
4036 END LOOP;
4037 END GENERATE_DYNAMIC_LOGIC;
4038 ---------------------------------------------------------------------------------------
4039 PROCEDURE GENERATE_NUMERIC_RULE IS
4040
4041 v_index PLS_INTEGER;
4042 BEGIN
4043
4044 IF(jAntecedentRoot IS NULL OR jConsequentRoot IS NULL)THEN
4045 RAISE CZ_R_INVALID_NUMERIC_RULE;
4046 END IF;
4047
4048 IF(v_tExprType(jAntecedentRoot) = EXPR_OPERATOR AND (NOT v_ChildrenIndex.EXISTS(v_tExprId(jAntecedentRoot))))THEN
4049 RAISE CZ_R_INCOMPLETE_NUMERIC_RULE;
4050 END IF;
4051
4052 IF(HAS_INTEGER_VALUE(jConsequentRoot) = GENERATE_INCREMENT)THEN
4053
4054 --For a numeric rule, if RHS has an integer value, the antecedent root should be a rounding operator.
4055 --As a fix for the bug #3558699, we are making this check more flexible - we require the rounding
4056 --operator only if the data type of the antecedent is not convertible to integer.
4057 --As a fix for the bug #3764347, if the antecedent root is a multiply operator, we drill down into
4058 --its operands and check their data types.
4059
4060 IF(v_tExprType(jAntecedentRoot) <> EXPR_OPERATOR OR v_tExprSubtype(jAntecedentRoot) NOT IN
4061 (OPERATOR_ROUND, OPERATOR_CEILING, OPERATOR_FLOOR, OPERATOR_TRUNCATE))THEN
4062
4063 v_index := jAntecedentRoot;
4064 IF(v_tExprType(v_index) = EXPR_OPERATOR AND v_tExprSubtype(v_index) = OPERATOR_NONE)THEN
4065
4066 --Bug #4180719. This is an empty operator, drill down one level.
4067
4068 v_index:= v_ChildrenIndex(v_tExprId(v_index));
4069 END IF;
4070
4071 IF(v_tExprType(v_index) = EXPR_OPERATOR AND v_tExprSubtype(v_index) = OPERATOR_MULT)THEN
4072
4073 --This is a multiply operator, check the data types of the children.
4074
4075 v_index := v_ChildrenIndex(v_tExprId(v_index));
4076
4077 IF((NOT COMPATIBLE_DATA_TYPES(v_tExprDataType(v_index), DATA_TYPE_INTEGER)) OR
4078 (NOT COMPATIBLE_DATA_TYPES(v_tExprDataType(v_index + 1), DATA_TYPE_INTEGER)))THEN
4079
4080 RAISE CZ_R_INVALID_NUM_SIMPLE_EXPR;
4081 END IF;
4082 ELSIF(NOT COMPATIBLE_DATA_TYPES(v_tExprDataType(v_index), DATA_TYPE_INTEGER))THEN
4083
4084 RAISE CZ_R_INVALID_NUM_SIMPLE_EXPR;
4085 END IF;
4086 END IF;
4087
4088 GENERATE_INCREMENT_LOGIC;
4089 ELSIF(HAS_INTEGER_VALUE(jConsequentRoot) = GENERATE_CONTRIBUTE)THEN
4090 GENERATE_CONTRIBUTE_LOGIC;
4091 ELSIF(HAS_INTEGER_VALUE(jConsequentRoot) = GENERATE_DYNAMIC)THEN
4092 GENERATE_DYNAMIC_LOGIC;
4093 ELSE
4094 RAISE CZ_R_PARAMETER_NOT_FOUND;
4095 END IF;
4096 END;
4097 ---------------------------------------------------------------------------------------
4098 PROCEDURE GENERATE_COMPARISON_RULE IS
4099 leftOper tStringArray;
4100 rightOper tStringArray;
4101 ListType PLS_INTEGER;
4102 jRoot PLS_INTEGER;
4103 jChild PLS_INTEGER;
4104 BEGIN
4105
4106 IF(jAntecedentRoot IS NULL OR jConsequentRoot IS NULL)THEN
4107 RAISE CZ_R_INVALID_COMPARISON_RULE;
4108 END IF;
4109
4110 leftOper := GENERATE_EXPRESSION(jAntecedentRoot, ListType);
4111
4112 jRoot := jConsequentRoot;
4113
4114 IF(v_tExprType(jRoot) = EXPR_OPERATOR AND v_tExprSubtype(jRoot) IN (OPERATOR_ALLOF, OPERATOR_ANYOF) AND
4115 v_NumberOfChildren(v_tExprId(jRoot)) = 1)THEN
4116
4117 jChild := v_ChildrenIndex(v_tExprId(jRoot));
4118 IF(v_tExprType(jChild) = EXPR_PSNODE AND (NOT v_ChildrenIndex.EXISTS(v_tExprId(jChild))))THEN
4119
4120 jRoot := jChild;
4121 END IF;
4122 END IF;
4123
4124 rightOper := GENERATE_EXPRESSION(jRoot, ListType);
4125
4126 vLogicLine := 'GS' || OperatorLetters(nRuleOperator) || '... ' || TO_CHAR(nReasonId) || NewLine ||
4127 'GL' || OperatorLetters(OPERATOR_ALLOF) || leftOper(1) || NewLine ||
4128 'GR' || OperatorLetters(OPERATOR_ALLOF) || rightOper(1) || NewLine;
4129
4130 PACK;
4131 END;
4132 ---------------------------------------------------------------------------------------
4133 FUNCTION GENERATE_LOGIC_TREE(j IN PLS_INTEGER) RETURN tStringArray IS
4134 v_return tStringArray;
4135 BEGIN
4136
4137 IF((NOT v_ChildrenIndex.EXISTS(v_tExprId(j))) OR v_NumberOfChildren(v_tExprId(j)) <> 2)THEN
4138 RAISE CZ_R_INVALID_LOGIC_RULE;
4139 END IF;
4140
4141 nRuleOperator := v_tExprSubtype(j);
4142 jAntecedentRoot := v_ChildrenIndex(v_tExprId(j));
4143 jConsequentRoot := jAntecedentRoot + 1;
4144
4145 v_tExprParentId(jAntecedentRoot) := NULL;
4146 v_tExprParentId(jConsequentRoot) := NULL;
4147
4148 --High-level logic rule validation section. Should not do these validations for comparison rules.
4149 --Make sure antecedent and consequent nodes have logical value.
4150 --If this is a comparison rule with a DEFAULT operator, which was not allowed before, we will
4151 --generate this rule as a logic rule (bug #3343569).
4152
4153 IF(RuleTemplateType = RULE_TYPE_LOGIC_RULE OR nPresentationFlag = FLAG_FREEFORM_RULE OR
4154 nRuleOperator = RULE_OPERATOR_DEFAULTS)THEN
4155
4156 nRuleType := RULE_TYPE_LOGIC_RULE;
4157
4158 IF(NOT HAS_LOGICAL_VALUE(jAntecedentRoot))THEN
4159 nParam := jAntecedentRoot;
4160 IF(v_tExprPsNodeId(nParam) IS NULL)THEN
4161 localString := NULL;
4162 ELSE
4163 localString := glName(glIndexByPsNodeId(v_tExprPsNodeId(nParam)));
4164 END IF;
4165
4166 RAISE CZ_R_LOGIC_RULE_WRONG_FEAT;
4167 END IF;
4168
4169 IF(NOT HAS_LOGICAL_VALUE(jConsequentRoot))THEN
4170 nParam := jConsequentRoot;
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 GENERATE_LOGIC_RULE;
4181
4182 ELSIF(RuleTemplateType = RULE_TYPE_COMPARISON_RULE)THEN
4183
4184 nRuleType := RULE_TYPE_COMPARISON_RULE;
4185 GENERATE_COMPARISON_RULE;
4186
4187 ELSE
4188
4189 RAISE CZ_R_UNKNOWN_RULE_TYPE;
4190 END IF;
4191 RETURN v_return;
4192 END;
4193 ---------------------------------------------------------------------------------------
4194 FUNCTION GENERATE_NUMERIC_TREE(j IN PLS_INTEGER) RETURN tStringArray IS
4195 v_return tStringArray;
4196 BEGIN
4197
4198 IF((NOT v_ChildrenIndex.EXISTS(v_tExprId(j))) OR v_NumberOfChildren(v_tExprId(j)) <> 2)THEN
4199 RAISE CZ_R_INVALID_NUMERIC_RULE;
4200 END IF;
4201
4202 nRuleType := RULE_TYPE_NUMERIC_RULE;
4203
4204 nRuleOperator := v_tExprSubtype(j);
4205 jAntecedentRoot := v_ChildrenIndex(v_tExprId(j));
4206 jConsequentRoot := jAntecedentRoot + 1;
4207
4208 v_tExprParentId(jAntecedentRoot) := NULL;
4209 v_tExprParentId(jConsequentRoot) := NULL;
4210
4211 --High-level numeric rule validation section.
4212 --Make sure participating features have correct types.
4213
4214 FOR i IN expressionStart..expressionEnd LOOP
4215 IF(v_tExprPsNodeId(i) IS NOT NULL)THEN
4216
4217 localMinimum := glIndexByPsNodeId(v_tExprPsNodeId(i));
4218
4219 IF(glPsNodeType(localMinimum) = PS_NODE_TYPE_FEATURE AND
4220 glFeatureType(localMinimum) = PS_NODE_FEATURE_TYPE_STRING)THEN
4221
4222 nParam := i;
4223 RAISE CZ_R_NUMERIC_RULE_WRONG_FEAT;
4224 END IF;
4225
4226 IF(i = jConsequentRoot AND trackableAncestor.EXISTS(v_tExprPsNodeId(i)))THEN
4227
4228 --This node is an ancestor of a BOM trackable item. It should be prohibited from
4229 --participating on the RHS of a numeric rule.
4230
4231 nParam := glIndexByPsNodeId(v_tExprPsNodeId(i));
4232 RAISE CZ_R_TRACKABLE_ANCESTOR;
4233 END IF;
4234 END IF;
4235 END LOOP;
4236
4237 GENERATE_NUMERIC_RULE;
4238 RETURN v_return;
4239 END;
4240 ---------------------------------------------------------------------------------------
4241 FUNCTION GENERATE_TEMPLATE_APPLICATION(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER)
4242 RETURN tStringArray IS
4243
4244 v_return tStringArray;
4245 h_mapExprId tIntegerArray;
4246
4247 jdef PLS_INTEGER;
4248 templateStart PLS_INTEGER;
4249 templateEnd PLS_INTEGER;
4250 v_index PLS_INTEGER;
4251
4252 ---------------------------------------------------------------------------------------
4253 PROCEDURE READ_TEMPLATE(p_template_id IN NUMBER) IS
4254
4255 --These are local arrays used only to transfer data to the relevant expression arrays.
4256
4257 v_NodeId tExplNodeId;
4258 v_Type tExprType;
4259 v_Subtype tExprSubtype;
4260 v_Id tExprId;
4261 v_ParentId tExprParentId;
4262 v_TemplateId tExprTemplateId;
4263 v_ExpressId tExpressId;
4264 v_PsNodeId tExplNodeId;
4265 v_DataValue tExprDataValue;
4266 v_PropertyId tExprPropertyId;
4267 v_ArgumentIndex tExprArgumentIndex;
4268 v_ArgumentName tExprArgumentName;
4269 v_ConsequentFlag tConsequentFlag;
4270 v_DataNumValue tExprDataNumValue;
4271 v_DataType tExprDataType;
4272
4273 BEGIN
4274
4275 nDebug := 8010100;
4276
4277 IF(NOT memoryTemplateStart.EXISTS(p_template_id))THEN
4278
4279 SELECT model_ref_expl_id, expr_type, expr_node_id, expr_parent_id, template_id,
4280 express_id, expr_subtype, ps_node_id, data_value, property_id, argument_index,
4281 argument_name, consequent_flag, data_num_value, data_type
4282 BULK COLLECT INTO v_NodeId, v_Type, v_Id, v_ParentId, v_TemplateId,
4283 v_ExpressId, v_Subtype, v_PsNodeId, v_DataValue, v_PropertyId, v_ArgumentIndex,
4284 v_ArgumentName, v_ConsequentFlag, v_DataNumValue, v_DataType
4285 FROM cz_expression_nodes
4286 WHERE rule_id = p_template_id
4287 AND expr_type <> EXPR_NODE_TYPE_PUNCT
4288 AND deleted_flag = FLAG_NOT_DELETED
4289 ORDER BY expr_parent_id, seq_nbr;
4290
4291 nDebug := 8010101;
4292
4293 IF(v_Id.COUNT = 0)THEN
4294 RAISE CZ_R_TEMPLATE_UNKNOWN;
4295 END IF;
4296
4297 v_index := v_tTmplId.COUNT + 1;
4298 memoryTemplateStart(p_template_id) := v_index;
4299
4300 nDebug := 8010102;
4301
4302 FOR i IN 1..v_Id.COUNT LOOP
4303
4304 IF(v_DataNumValue(i) IS NOT NULL)THEN v_DataValue(i) := TO_CHAR(v_DataNumValue(i)); END IF;
4305
4306 v_tTmplNodeId(v_index) := v_NodeId(i);
4307 v_tTmplType(v_index) := v_Type(i);
4308 v_tTmplSubtype(v_index) := v_Subtype(i);
4309 v_tTmplId(v_index) := v_Id(i);
4310 v_tTmplParentId(v_index) := v_ParentId(i);
4311 v_tTmplTemplateId(v_index) := v_TemplateId(i);
4312 v_tTmplExpressId(v_index) := v_ExpressId(i);
4313 v_tTmplPsNodeId(v_index) := v_PsNodeId(i);
4314 v_tTmplPropertyId(v_index) := v_PropertyId(i);
4315 v_tTmplArgumentIndex(v_index) := v_ArgumentIndex(i);
4316 v_tTmplArgumentName(v_index) := v_ArgumentName(i);
4317 v_tTmplConsequent(v_index) := v_ConsequentFlag(i);
4318 v_tTmplDataValue(v_index) := v_DataValue(i);
4319 v_tTmplDataType(v_index) := v_DataType(i);
4320
4321 v_index := v_index + 1;
4322 END LOOP;
4323
4324 memoryTemplateEnd(p_template_id) := v_tTmplId.COUNT;
4325 END IF;
4326 END;
4327 ---------------------------------------------------------------------------------------
4328 FUNCTION COPY_EXPRESSION_NODE(j_from IN PLS_INTEGER, j_parent IN PLS_INTEGER)
4329 RETURN PLS_INTEGER IS
4330 j_to PLS_INTEGER;
4331 BEGIN
4332
4333 nDebug := 8010105;
4334
4335 j_to := v_tExprId.COUNT + 1;
4336 nLocalExprId := nLocalExprId + 1;
4337
4338 v_tExprId(j_to) := nLocalExprId;
4339 v_tExprParentId(j_to) := j_parent;
4340
4341 v_tExplNodeId(j_to) := v_tExplNodeId(j_from);
4342 v_tExprType(j_to) := v_tExprType(j_from);
4343 v_tExprSubtype(j_to) := v_tExprSubtype(j_from);
4344 v_tExprTemplateId(j_to) := v_tExprTemplateId(j_from);
4345 v_tExprParamIndex(j_to) := v_tExprParamIndex(j_from);
4346 v_tExprParSignature(j_to) := v_tExprParSignature(j_from);
4347 v_tExpressId(j_to) := v_tExpressId(j_from);
4348 v_tExprPsNodeId(j_to) := v_tExprPsNodeId(j_from);
4349 v_tExprDataValue(j_to) := v_tExprDataValue(j_from);
4350 v_tExprDataType(j_to) := v_tExprDataType(j_from);
4351 v_tExprPropertyId(j_to) := v_tExprPropertyId(j_from);
4352 v_tConsequentFlag(j_to) := v_tConsequentFlag(j_from);
4353 v_tExprArgumentName(j_to) := v_tExprArgumentName(j_from);
4354
4355 nDebug := 8010106;
4356
4357 RETURN j_to;
4358 END;
4359 ---------------------------------------------------------------------------------------
4360 PROCEDURE COPY_EXPRESSION_TREE(j_from IN PLS_INTEGER, j_parent IN PLS_INTEGER) IS
4361 j_child PLS_INTEGER;
4362 j_children tIntegerArray;
4363 BEGIN
4364
4365 nDebug := 8010107;
4366
4367 IF(v_ChildrenIndex.EXISTS(v_tExprId(j_from)))THEN
4368
4369 j_child := v_ChildrenIndex(v_tExprId(j_from));
4370
4371 WHILE(v_tExprParentId(j_child) = v_tExprId(j_from))LOOP
4372
4373 j_children(j_child) := COPY_EXPRESSION_NODE(j_child, j_parent);
4374 j_child := j_child + 1;
4375 END LOOP;
4376
4377 j_child := v_ChildrenIndex(v_tExprId(j_from));
4378
4379 WHILE(v_tExprParentId(j_child) = v_tExprId(j_from))LOOP
4380
4381 COPY_EXPRESSION_TREE(j_child, j_children(j_child));
4382 j_child := j_child + 1;
4383 END LOOP;
4384 END IF;
4385
4386 nDebug := 8010108;
4387
4388 END;
4389 ---------------------------------------------------------------------------------------
4390 BEGIN
4391
4392 RuleTemplateType := v_tExprSubtype(j);
4393 READ_TEMPLATE(RuleTemplateType);
4394 templateStart := v_tExprId.COUNT + 1;
4395
4396 FOR i IN memoryTemplateStart(RuleTemplateType)..memoryTemplateEnd(RuleTemplateType) LOOP
4397
4398 IF(v_tTmplType(i) = EXPR_ARGUMENT AND v_tTmplArgumentIndex(i) IS NOT NULL)THEN
4399
4400 nDebug := 8010109;
4401
4402 --This is an argument, may correspond to a collection of paramaters in the template
4403 --application.
4404
4405 jdef := 0;
4406
4407 FOR ii IN expressionStart..expressionEnd LOOP
4408
4409 IF(v_tExprParamIndex(ii) = v_tTmplArgumentIndex(i))THEN
4410
4411 jdef := 1;
4412 v_index := v_tExprId.COUNT + 1;
4413 nLocalExprId := nLocalExprId + 1;
4414
4415 v_tExprId(v_index) := nLocalExprId;
4416 h_mapExprId(v_tExprId(ii)) := nLocalExprId;
4417
4418 --If this entry gets overwritten many times, it is not a problem because in this case it
4419 --will never be used.
4420
4421 h_mapExprId(v_tTmplId(i)) := nLocalExprId;
4422
4423 v_tExprParentId(v_index) := v_tTmplParentId(i);
4424 v_tExplNodeId(v_index) := v_tExplNodeId(ii);
4425 v_tExprType(v_index) := v_tExprType(ii);
4426 v_tExprSubtype(v_index) := v_tExprSubtype(ii);
4427 v_tExprTemplateId(v_index) := v_tExprTemplateId(ii);
4428 v_tExpressId(v_index) := v_tExpressId(ii);
4429 v_tExprPsNodeId(v_index) := v_tExprPsNodeId(ii);
4430 v_tExprDataValue(v_index) := v_tExprDataValue(ii);
4431 v_tExprDataType(v_index) := v_tExprDataType(ii);
4432 v_tExprPropertyId(v_index) := v_tExprPropertyId(ii);
4433 v_tConsequentFlag(v_index) := v_tConsequentFlag(ii);
4434 v_tExprArgumentName(v_index) := v_tExprArgumentName(ii);
4435 v_tExprParamIndex(v_index) := v_tExprParamIndex(ii);
4436 v_tExprParSignature(v_index) := v_tExprParSignature(ii);
4437
4438 IF(v_tExprType(v_index) = EXPR_TEMPLATE)THEN v_tExprType(v_index) := EXPR_OPERATOR; END IF;
4439 END IF;
4440 END LOOP;
4441
4442 --No parameter was found for this argument - incomplete rule.
4443
4444 IF(jdef = 0)THEN RAISE CZ_R_INCORRECT_NODE_ID; END IF;
4445 ELSE
4446
4447 nDebug := 8010110;
4448
4449 --This is a regular node in the template definition, just copy.
4450
4451 v_index := v_tExprId.COUNT + 1;
4452 nLocalExprId := nLocalExprId + 1;
4453
4454 v_tExprId(v_index) := nLocalExprId;
4455 h_mapExprId(v_tTmplId(i)) := nLocalExprId;
4456
4457 v_tExprParentId(v_index) := v_tTmplParentId(i);
4458 v_tExplNodeId(v_index) := v_tTmplNodeId(i);
4459 v_tExprType(v_index) := v_tTmplType(i);
4460 v_tExprSubtype(v_index) := v_tTmplSubtype(i);
4461 v_tExprTemplateId(v_index) := v_tTmplTemplateId(i);
4462 v_tExpressId(v_index) := v_tTmplExpressId(i);
4463 v_tExprPsNodeId(v_index) := v_tTmplPsNodeId(i);
4464 v_tExprDataValue(v_index) := v_tTmplDataValue(i);
4465 v_tExprDataType(v_index) := v_tTmplDataType(i);
4466 v_tExprPropertyId(v_index) := v_tTmplPropertyId(i);
4467 v_tConsequentFlag(v_index) := v_tTmplConsequent(i);
4468 v_tExprArgumentName(v_index) := v_tTmplArgumentName(i);
4469 END IF;
4470 END LOOP;
4471
4472 nDebug := 8010111;
4473
4474 templateEnd := v_tExprId.COUNT;
4475
4476 FOR i IN templateStart..templateEnd LOOP
4477
4478 IF(v_tExprParentId(i) IS NOT NULL)THEN
4479
4480 IF(NOT h_mapExprId.EXISTS(v_tExprParentId(i)))THEN RAISE CZ_R_INCORRECT_NODE_ID; END IF;
4481 v_tExprParentId(i) := h_mapExprId(v_tExprParentId(i));
4482 END IF;
4483 END LOOP;
4484
4485 nDebug := 8010112;
4486
4487 FOR i IN expressionStart..expressionEnd LOOP
4488
4489 IF(h_mapExprId.EXISTS(v_tExprId(i)))THEN
4490
4491 COPY_EXPRESSION_TREE(i, h_mapExprId(v_tExprId(i)));
4492 END IF;
4493 END LOOP;
4494
4495 expressionStart := templateStart;
4496 expressionEnd := v_tExprId.COUNT;
4497
4498 nDebug := 8010114;
4499
4500 --We need to populate all the auxiliary arrays because now this is the expression we will be
4501 --processing. We don't really have to empty these arrays.
4502
4503 v_IndexByExprNodeId.DELETE;
4504 v_NumberOfChildren.DELETE;
4505 v_ChildrenIndex.DELETE;
4506
4507 FOR i IN expressionStart..expressionEnd LOOP
4508
4509 v_tExprSubtype(i) := v_tExprTemplateId(i);
4510
4511 --Add the indexing option.
4512
4513 v_IndexByExprNodeId(v_tExprId(i)) := i;
4514
4515 IF(v_tExprParentId(i) IS NOT NULL)THEN
4516
4517 IF(v_NumberOfChildren.EXISTS(v_tExprParentId(i)))THEN
4518 v_NumberOfChildren(v_tExprParentId(i)) := v_NumberOfChildren(v_tExprParentId(i)) + 1;
4519 ELSE
4520 v_NumberOfChildren(v_tExprParentId(i)) := 1;
4521 END IF;
4522
4523 IF(NOT v_ChildrenIndex.EXISTS(v_tExprParentId(i)))THEN
4524 v_ChildrenIndex(v_tExprParentId(i)) := i;
4525 END IF;
4526
4527 ELSE
4528
4529 --This is the root of the exploded template application expression tree.
4530
4531 jdef := i;
4532 END IF;
4533
4534 nDebug := 8010115;
4535
4536 END LOOP;
4537
4538 nDebug := 8010116;
4539
4540 v_return := GENERATE_EXPRESSION(jdef, ListType);
4541 RETURN v_return;
4542 END;
4543 ---------------------------------------------------------------------------------------
4544 FUNCTION LOOKUP_ARGUMENT(j IN PLS_INTEGER) RETURN PLS_INTEGER IS
4545 argIndex PLS_INTEGER := 0;
4546 BEGIN
4547
4548 IF(parameterScope.COUNT = 0)THEN
4549 RAISE CZ_R_EMPTY_PARAMETER_SCOPE;
4550 END IF;
4551
4552 FOR i IN 1..parameterName.COUNT LOOP
4553 IF(parameterName(i) = v_tExprArgumentName(j))THEN argIndex := i; EXIT; END IF;
4554 END LOOP;
4555
4556 IF(argIndex = 0)THEN
4557 RAISE CZ_R_PARAMETER_NOT_FOUND;
4558 END IF;
4559
4560 RETURN argIndex;
4561 END;
4562 ---------------------------------------------------------------------------------------
4563 FUNCTION GENERATE_ARGUMENT(j IN PLS_INTEGER, ListType IN OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
4564 v_return tStringArray;
4565 argIndex PLS_INTEGER := 0;
4566 BEGIN
4567
4568 nDebug := 7004010;
4569
4570 --The procedure can be called with a particular ListType to get a specific field from the
4571 --parameter scope.
4572 --Call with ListType = 0 to get the data type from cz_expression_nodes.
4573 --When called with ListType NULL, generate name or return value field.
4574
4575 --Bug #4681261 - with re-using of temporary tables, we cannot use stored generated names
4576 --anymore because these names depend not only on ps_node_id, model_ref_expl_id but also
4577 --on where the rule is assined. Therefore need to generate the name here instead of in
4578 --generate_iterator.
4579
4580 argIndex := LOOKUP_ARGUMENT(j);
4581
4582 v_tExprPsNodeId(j) := parameterScope(argIndex).node_id;
4583 v_tExplNodeId(j) := parameterScope(argIndex).node_id_ex;
4584
4585 --If this is a node, generate name here.
4586
4587 IF(v_tExprPsNodeId(j) IS NOT NULL AND v_tExplNodeId(j) IS NOT NULL AND
4588 parameterScope(argIndex).node_value IS NULL AND parameterScope(argIndex).node_obj IS NULL)THEN
4589
4590 v_return(1) := GENERATE_NAME_EXPL(v_tExplNodeId(j), v_tExprPsNodeId(j));
4591 parameterScope(argIndex).node_value := v_return(1);
4592 parameterScope(argIndex).node_obj := v_return(1);
4593 END IF;
4594
4595 IF(ListType = DATA_TYPE_VOID)THEN ListType := v_tExprDataType(j); END IF;
4596 IF(ListType IN (DATA_TYPE_INTEGER, DATA_TYPE_DECIMAL, DATA_TYPE_BOOLEAN, DATA_TYPE_TEXT))THEN
4597
4598 v_return(1) := parameterScope(argIndex).node_value;
4599 ELSIF(ListType = DATA_TYPE_NODE)THEN
4600
4601 v_return(1) := parameterScope(argIndex).node_id;
4602 ELSIF(ListType = DATA_TYPE_VARIANT)THEN
4603
4604 v_return(1) := parameterScope(argIndex).node_obj;
4605 ELSE
4606
4607 v_return(1) := parameterScope(argIndex).node_value;
4608 END IF;
4609
4610 nDebug := 7004019;
4611
4612 RETURN v_return;
4613 END;
4614 ---------------------------------------------------------------------------------------
4615 FUNCTION GENERATE_FORALL(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tIteratorArray;
4616 ---------------------------------------------------------------------------------------
4617 FUNCTION GENERATE_REFNODE(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
4618 v_children tIntegerArray;
4619 v_object VARCHAR2(128);
4620 nodeChild PLS_INTEGER;
4621 featChild PLS_INTEGER;
4622 featPsNodeId NUMBER; --kdande; Bug 6881902; 11-Mar-2008
4623 LocalType PLS_INTEGER;
4624 IsNumeric PLS_INTEGER;
4625 IsNotZero PLS_INTEGER;
4626 nCheck NUMBER;
4627 countTrue PLS_INTEGER := 0;
4628 countFalse PLS_INTEGER := 0;
4629 v_actual VARCHAR2(16) := ' ';
4630 v_return tStringArray;
4631 v_propval tStringArray;
4632 v_psnode tStringArray;
4633 CurrentId PLS_INTEGER;
4634 nodeId NUMBER; --jonatara:bug7041718
4635 v_sysprop PLS_INTEGER;
4636 v_mutable VARCHAR2(1);
4637 v_collection VARCHAR2(1);
4638 v_context PLS_INTEGER;
4639 BEGIN
4640
4641 nDebug := 7004070;
4642
4643 CurrentId := v_tExprId(j);
4644 nodeChild := v_ChildrenIndex(CurrentId);
4645 nLocalDefaults := nLocalDefaults + 1;
4646
4647 IF(v_tExprType(j) = EXPR_ARGUMENT)THEN
4648
4649 --This is an argument, we assume that it is of type 'node'.
4650
4651 LocalType := DATA_TYPE_NODE;
4652 v_return := GENERATE_ARGUMENT(j, LocalType);
4653
4654 ELSE
4655
4656 --It's not an argument, so it's a ps_node.
4657
4658 v_return(1) := TO_CHAR(v_tExprPsNodeId(j));
4659 END IF;
4660
4661 nodeId := v_return(1);
4662
4663 WHILE(v_tExprParentId.EXISTS(nodeChild) AND v_tExprParentId(nodeChild) = CurrentId)LOOP
4664 IF(v_tExplNodeId(nodeChild) IS NULL OR v_tExplNodeId(nodeChild) = -1 OR
4665
4666 --Bug #3821827, caused by a corruption, when the explosion_id value was neither NULL or -1,
4667 --but was just some incorrect value when it is expected to be NULL.
4668
4669 (NOT v_NodeLogicLevel.EXISTS(v_tExplNodeId(nodeChild))))THEN
4670
4671 v_tExplNodeId(nodeChild) := v_ExplByPsNodeId(nodeId);
4672 END IF;
4673
4674 IF(h_SeededName.EXISTS(v_tExprSubtype(nodeChild)) AND h_SeededName(v_tExprSubtype(nodeChild)) = RULE_SYS_PROP_SELECTION)THEN
4675
4676 featChild := v_ChildrenIndex(CurrentId);
4677 featPsNodeId := v_return(1);
4678 v_children := EXPAND_NODE_OPTIONAL(featPsNodeId);
4679 v_sysprop := nodeChild + 1;
4680 LocalType := DATA_TYPE_VOID;
4681 v_context := 1;
4682
4683 IF(v_tExprParentId.EXISTS(v_sysprop) AND v_tExprParentId(v_sysprop) = CurrentId)THEN
4684
4685 --The system property was explicitly specified.
4686
4687 nDebug := 7004073;
4688
4689 IF(v_tExprType(v_sysprop) = EXPR_NODE_TYPE_SYSPROP)THEN
4690 IF(NOT h_SeededName.EXISTS(v_tExprSubtype(v_sysprop)))THEN RAISE CZ_E_BAD_PROPERTY_TYPE; END IF;
4691
4692 IF(NOT APPLICABLE_SYS_PROP(j, glPsNodeId(v_children(1)), v_tExprSubtype(v_sysprop)))THEN
4693
4694 auxIndex := v_children(1);
4695 localString := h_ReportName(v_tExprSubtype(v_sysprop));
4696 RAISE CZ_R_INCOMPATIBLE_SYSPROP;
4697 END IF;
4698 END IF;
4699
4700 v_tExplNodeId(v_sysprop) := v_ExplByPsNodeId(nodeId);
4701 v_context := 0;
4702 ELSE
4703
4704 --This is Node.Selection(), the actual system property is not specified. It can be either .State()
4705 --or .Quantity() depending on the context.
4706
4707 IF(COMPATIBLE_DATA_TYPES(GET_ARGUMENT_INFO(v_tExprParamIndex(j), v_tExprParSignature(j),
4708 v_mutable, v_collection), DATA_TYPE_BOOLEAN))THEN
4709 --The context is boolean.
4710
4711 nDebug := 7004071;
4712
4713 IF(NOT APPLICABLE_SYS_PROP(j, NULL, RULE_SYS_PROP_STATE))THEN
4714
4715 auxIndex := glIndexByPsNodeId(nodeId);
4716 localString := 'State';
4717 RAISE CZ_R_INCOMPATIBLE_SYSPROP;
4718 END IF;
4719
4720 ListType := DATA_TYPE_BOOLEAN;
4721 v_return.DELETE;
4722 v_return(1) := GENERATE_NAME(j, nodeId);
4723
4724 --This is Feature.Selection().State(), which in a boolean context is equivalent to Feature.
4725
4726 EXIT;
4727 ELSE
4728
4729 --The context is numeric.
4730
4731 nDebug := 7004072;
4732
4733 IF(NOT APPLICABLE_SYS_PROP(j, glPsNodeId(v_children(1)), RULE_SYS_PROP_QUANTITY))THEN
4734
4735 auxIndex := v_children(1);
4736 localString := 'Quantity';
4737 RAISE CZ_R_INCOMPATIBLE_SYSPROP;
4738 END IF;
4739
4740 LocalType := DATA_TYPE_DECIMAL;
4741 END IF;
4742 END IF;
4743
4744 v_return.DELETE;
4745
4746 IF(nRuleType = RULE_TYPE_NUMERIC_RULE AND v_context = 0 AND
4747 v_tExprType(v_sysprop) = EXPR_NODE_TYPE_SYSPROP AND
4748 h_SeededName(v_tExprSubtype(v_sysprop)) = RULE_SYS_PROP_STATE)THEN
4749
4750 --This is Node.Selection().State() in a numeric rule, State() was explicitly specified.
4751 --Bugs #4198455, #4366598.
4752
4753 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
4754 vLogicLine := 'OBJECT ' || v_return(1) || NewLine;
4755 PACK;
4756
4757 FOR i IN 1..v_children.COUNT LOOP
4758
4759 vLogicLine := 'OBJECT ' || v_return(1) || '_' || TO_CHAR(i) || NewLine ||
4760 'GS I ... ' || TO_CHAR(nReasonId) || NewLine ||
4761 'GL' || OperatorLetters(OPERATOR_ANYOF) || GENERATE_NAME(j, glPsNodeId(v_children(i))) || NewLine ||
4762 'GR' || OperatorLetters(OPERATOR_ANYOF) || v_return(1) || '_' || TO_CHAR(i) || NewLine;
4763 PACK;
4764
4765 vLogicLine := 'INC ' || v_return(1) || '_' || TO_CHAR(i) || ' ' || v_return(1) ||
4766 OperatorLiterals(OPERATOR_ROUND) || '... ' || TO_CHAR(nReasonId) || NewLine;
4767 PACK;
4768 END LOOP;
4769
4770 RETURN v_return;
4771 END IF;
4772
4773 FOR i IN 1..v_children.COUNT LOOP
4774
4775 v_propval(1) := TO_CHAR(glPsNodeId(v_children(i)));
4776
4777 IF(v_context = 1)THEN v_propval(1) := GENERATE_NAME(j, glPsNodeId(v_children(i)));
4778 ELSE v_propval := SYSTEM_PROPERTY_VALUE(v_sysprop, v_propval, LocalType); END IF;
4779 ListType := LocalType;
4780
4781 BEGIN
4782 nCheck := TO_NUMBER(v_propval(1));
4783 IsNumeric := 1;
4784 IsNotZero := 1;
4785 IF(nCheck = 0)THEN
4786 IsNotZero := 0;
4787 END IF;
4788 EXCEPTION
4789 WHEN OTHERS THEN
4790 IsNumeric := 0;
4791 IsNotZero := 1;
4792 END;
4793
4794 IF(LocalType IN (DATA_TYPE_INTEGER, DATA_TYPE_DECIMAL))THEN
4795
4796 v_object := t_prefix || TO_CHAR(nLocalDefaults) || '_' || TO_CHAR(i);
4797
4798 IF(IsNumeric = 1)THEN
4799
4800 --If a number, we have to GATE it throught the real option. We will do
4801 --it even if the property value is 0 for consistency.
4802
4803 vLogicLine := 'OBJECT ' || v_object || NewLine ||
4804 'GS I ... ' || TO_CHAR(nReasonId) || NewLine ||
4805 'GL' || OperatorLetters(OPERATOR_ANYOF) || GENERATE_NAME(featChild, glPsNodeId(v_children(i))) || NewLine ||
4806 'GR' || OperatorLetters(OPERATOR_ANYOF) || v_object || NewLine;
4807 ELSE
4808
4809 --If the property value is not numeric, then it is a "P_" name returned
4810 --as a result of Feat.#Selection.Count. In this case we have to GATE it
4811 --by making an INC from the real option. This prevents from propagating
4812 --when the option is FALSE.
4813
4814 vLogicLine := 'OBJECT ' || v_object || NewLine ||
4815 'INC ' || GENERATE_NAME(featChild, glPsNodeId(v_children(i))) || ' ' || v_object ||
4816 OperatorLiterals(OPERATOR_NONE) ||
4817 '... ' || TO_CHAR(nReasonId) || NewLine;
4818 END IF;
4819
4820 PACK;
4821
4822 IF(NOT v_return.EXISTS(1))THEN
4823
4824 v_return(1) := t_prefix || TO_CHAR(nLocalDefaults);
4825 vLogicLine := 'TOTAL ' || v_return(1) || NewLine;
4826 PACK;
4827 END IF;
4828
4829 --In any case we multiply the property count (a number if it's .property or
4830 --the actual option if it is .#Count) by the intermediate object (the gate)
4831 --which is only true if the option is true. That way if no options selected
4832 --the result will be UNKNOWN.
4833
4834 IF(IsNumeric = 0)THEN
4835
4836 --If the property is not numeric then we multiply by 1 because it is the
4837 --count of the option.
4838
4839 vLogicLine := 'CONTRIBUTE ' || v_object || OperatorLiterals(OPERATOR_MULT) ||
4840 '1 ' || v_return(1) || v_actual || '... ' || TO_CHAR(nReasonId) || NewLine;
4841
4842 ELSIF(IsNotZero = 1)THEN
4843
4844 --If the property is not zero we have to multiply the gate by the property.
4845
4846 vLogicLine := 'CONTRIBUTE ' || v_object || OperatorLiterals(OPERATOR_MULT) ||
4847 v_propval(1) || ' ' || v_return(1) || v_actual || '... ' || TO_CHAR(nReasonId) || NewLine;
4848
4849 ELSE
4850
4851 --If the property value is 0, we will subtract the gate from the gate. This
4852 --is required in order to propagate 0 only if the option is selected. If we
4853 --used "gate * 0" it would always propagate 0, even if the gate is UNKNOWN,
4854 --and we don't want that to happen.
4855
4856 vLogicLine := 'CONTRIBUTE ' || v_object || OperatorLiterals(OPERATOR_SUB) ||
4857 v_object || ' ' || v_return(1) || v_actual || '... ' || TO_CHAR(nReasonId) || NewLine;
4858
4859 END IF;
4860 PACK;
4861
4862 ELSE
4863
4864 IF(LocalType <> DATA_TYPE_TEXT OR generateCompare = 1)THEN
4865
4866 v_return(i) := GENERATE_NAME(featChild, glPsNodeId(v_children(i))) || PROPERTY_DELIMITER || v_propval(1);
4867 ELSE
4868 --The expression contained a Text property which is only allowed in a comparison expression.
4869 --A Text property is not allowed in the context of your expression. Rule '%RULENAME' in
4870 --Model '%MODELNAME' ignored.
4871
4872 RAISE CZ_R_PROPERTY_NOT_ALLOWED;
4873 END IF;
4874 END IF;
4875 END LOOP;
4876
4877 IF(LocalType = DATA_TYPE_BOOLEAN)THEN
4878
4879 --The code inside this block has been changed as a fix for bug #1862896.
4880 --Start with creating gating objects and INC relations for all the extracted
4881 --options.
4882
4883 FOR i IN 1..v_return.COUNT LOOP
4884
4885 v_object := t_prefix || TO_CHAR(nLocalDefaults) || '_' || TO_CHAR(i);
4886 vLogicLine := 'OBJECT ' || v_object || NewLine ||
4887 'INC ' || EXTRACT_PROPERTY_NODE(v_return(i)) || ' ' || v_object ||
4888 OperatorLiterals(OPERATOR_ROUND) || '... ' || TO_CHAR(nReasonId) || NewLine;
4889
4890 --We are going to calculate the counts of true/false options in order to decide whether
4891 --we need to include the unsatisfied message id in the following GS relations. First we
4892 --overwrite the concatenated name/property value string in v_return to be just property
4893 --value as we don't use the concatenated format of v_return in this branch anymore.
4894
4895 v_return(i) := EXTRACT_PROPERTY_VALUE(v_return(i));
4896 IF(v_return(i) = BOOLEAN_TRUE_REPRESENTATION)THEN countTrue := countTrue + 1;
4897 ELSIF(v_return(i) = BOOLEAN_FALSE_REPRESENTATION)THEN countFalse := countFalse + 1;
4898 END IF;
4899
4900 PACK;
4901 END LOOP;
4902
4903 --This is the resulting object that will be returned. Any of the TRUE gating
4904 --objects requires this object, any of the FALSE gating objects negates it.
4905
4906 v_object := t_prefix || TO_CHAR(nLocalDefaults);
4907 vLogicLine := 'OBJECT ' || v_object || NewLine;
4908
4909 IF(countTrue > 0)THEN
4910
4911 localString := NULL;
4912 IF(countTrue > 1)THEN localString := sUnsatisfiedId; END IF;
4913
4914 vLogicLine := vLogicLine || 'GS R ' || localString || '... ' || TO_CHAR(nReasonId) || NewLine ||
4915 'GL' || OperatorLetters(OPERATOR_ANYOF);
4916 PACK;
4917
4918 nDebug := 8001156;
4919
4920 --Generate the list of all the TRUE gating objects.
4921
4922 FOR i IN 1..v_return.COUNT LOOP
4923
4924 IF(v_return(i) = BOOLEAN_TRUE_REPRESENTATION)THEN
4925 vLogicLine := v_object || '_' || TO_CHAR(i) || ' ';
4926 PACK;
4927 END IF;
4928 END LOOP;
4929
4930 vLogicLine := NewLine || 'GR' || OperatorLetters(OPERATOR_ANYOF) || v_object || NewLine;
4931 END IF;
4932
4933 IF(countFalse > 0)THEN
4934
4935 localString := NULL;
4936 IF(countFalse > 1)THEN localString := sUnsatisfiedId; END IF;
4937
4938 vLogicLine := vLogicLine || 'GS N ' || localString || '... ' || TO_CHAR(nReasonId) || NewLine ||
4939 'GL' || OperatorLetters(OPERATOR_ANYOF);
4940 PACK;
4941
4942 nDebug := 8001157;
4943
4944 --Generate the list of all the FALSE gating objects.
4945
4946 FOR i IN 1..v_return.COUNT LOOP
4947
4948 IF(v_return(i) = BOOLEAN_FALSE_REPRESENTATION)THEN
4949 vLogicLine := v_object || '_' || TO_CHAR(i) || ' ';
4950 PACK;
4951 END IF;
4952 END LOOP;
4953
4954 vLogicLine := NewLine || 'GR' || OperatorLetters(OPERATOR_ANYOF) || v_object || NewLine;
4955 END IF;
4956 PACK;
4957
4958 v_return.DELETE;
4959 v_return(1) := v_object;
4960
4961 END IF;
4962
4963 --We don't need to move on as we already processed the following expression node(s).
4964
4965 EXIT;
4966 ELSE
4967
4968 IF(v_tExprType(nodeChild) = EXPR_NODE_TYPE_SYSPROP)THEN
4969 IF(NOT h_SeededName.EXISTS(v_tExprSubtype(nodeChild)))THEN RAISE CZ_E_BAD_PROPERTY_TYPE; END IF;
4970
4971 IF(NOT APPLICABLE_SYS_PROP(j, NULL, v_tExprSubtype(nodeChild)))THEN
4972
4973 auxIndex := glIndexByPsNodeId(nodeId);
4974 localString := h_ReportName(v_tExprSubtype(nodeChild));
4975 RAISE CZ_R_INCOMPATIBLE_SYSPROP;
4976 END IF;
4977 END IF;
4978
4979 v_propval := SYSTEM_PROPERTY_VALUE(nodeChild, v_return, ListType);
4980
4981 IF(ListType = DATA_TYPE_TEXT)THEN
4982
4983 --This is a direct user or system property of DATA_TYPE_TEXT. Currently we don't allow
4984 --any operations to work with strings other than the comparison operators, therefore we
4985 --are going from here back to the GENERATE_COMPARE procedure , which expects the output
4986 --to be a combination of the node's P_ name and the property value.
4987
4988 --This whole IF block is a part of the fix for the bug #1706286.
4989
4990 IF(generateCompare = 1)THEN
4991
4992 FOR i IN 1..v_propval.COUNT LOOP
4993
4994 v_return(i) := GENERATE_NAME(v_ChildrenIndex(CurrentId), v_return(i)) || PROPERTY_DELIMITER || v_propval(i);
4995 END LOOP;
4996 ELSIF(generateCollect = 1)THEN
4997
4998 --Exclusion from the above comment: we can be generating the COLLECT expression. Such expression
4999 --can contain references to text properties to be used for comparison in the WHERE clause, but
5000 --at this time we do not know that they will be used in comparison. We need to just return the
5001 --value of the property.
5002
5003 v_return := v_propval;
5004 ELSE
5005 --The expression contained a Text property which is only allowed in a comparison expression.
5006 --A Text property is not allowed in the context of your expression. Rule '%RULENAME' in
5007 --Model '%MODELNAME' ignored.
5008
5009 RAISE CZ_R_PROPERTY_NOT_ALLOWED;
5010 END IF;
5011 ELSIF(ListType = DATA_TYPE_BOOLEAN AND v_tExprType(nodeChild) = EXPR_PROP)THEN
5012
5013 --For boolean user properties we replace the 0/1 values with corresponding object names.
5014 --Bug #3371279.
5015
5016 FOR i IN 1..v_propval.COUNT LOOP
5017 IF(v_propval(i) = BOOLEAN_TRUE_REPRESENTATION)THEN v_return(i) := ALWAYS_TRUE;
5018 ELSE v_return(i) := ALWAYS_FALSE; END IF;
5019 END LOOP;
5020 ELSE
5021
5022 v_return := v_propval;
5023 END IF;
5024 END IF;
5025
5026 nodeChild := nodeChild + 1;
5027 END LOOP;
5028
5029 nDebug := 7004080;
5030
5031 RETURN v_return;
5032 END;
5033 ---------------------------------------------------------------------------------------
5034 FUNCTION GENERATE_ITERATOR(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tIteratorArray IS
5035
5036 v_return tIteratorArray;
5037 v_iterin tIteratorArray;
5038 nChild PLS_INTEGER;
5039 nCount PLS_INTEGER;
5040 nGrand PLS_INTEGER;
5041 nType PLS_INTEGER;
5042 v_result tIntegerArray;
5043 v_record tStringArray;
5044 nodeName VARCHAR2(4000);
5045
5046 BEGIN
5047
5048 nDebug := 7004000;
5049
5050 nChild := v_ChildrenIndex(v_tExprId(j));
5051
5052 WHILE(v_tExprParentId(nChild) = v_tExprId(j))LOOP
5053
5054 v_result.DELETE;
5055 v_record.DELETE;
5056 v_iterin.DELETE;
5057
5058 nCount := v_return.COUNT + 1;
5059
5060 IF(v_tExprType(nChild) = EXPR_PSNODE)THEN
5061 IF(v_ChildrenIndex.EXISTS(v_tExprId(nChild)))THEN
5062 IF(HAS_OPTIONS_APPLIED(nChild))THEN
5063
5064 IF(v_NumberOfChildren(v_tExprId(j)) = 1)THEN
5065
5066 temp_table_hash_key(forallLevel) := TO_CHAR(v_tExprPsNodeId(nChild)) || '-' || TO_CHAR(v_tExplNodeId(nChild));
5067 temp_cmpt_hash_key(compatLevel) := temp_table_hash_key(forallLevel);
5068 END IF;
5069
5070 v_result := EXPAND_NODE(nChild);
5071
5072 FOR i IN 1..v_result.COUNT LOOP
5073
5074 --Bug #4681261 - with re-using of temporary tables, we cannot use stored generated names
5075 --anymore because these names depend not only on ps_node_id, model_ref_expl_id but also
5076 --on where the rule is assined. Name will be generated in generate_argument.
5077 --nodeName := GENERATE_NAME_EXPL(v_ExplByPsNodeId(v_result(i)), v_result(i));
5078
5079 v_return(nCount).node_type := DATA_TYPE_NODE;
5080 v_return(nCount).node_value := NULL;
5081 v_return(nCount).node_id := v_result(i);
5082 v_return(nCount).node_obj := NULL;
5083 v_return(nCount).node_id_ex := v_ExplByPsNodeId(v_result(i));
5084
5085 nCount := nCount + 1;
5086 END LOOP;
5087 ELSE
5088
5089 v_record := GENERATE_REFNODE(nChild, ListType);
5090
5091 FOR i IN 1..v_record.COUNT LOOP
5092
5093 v_return(nCount).node_type := ListType;
5094 v_return(nCount).node_value := v_record(i);
5095 v_return(nCount).node_id := NULL;
5096 v_return(nCount).node_obj := v_record(i);
5097
5098 nCount := nCount + 1;
5099 END LOOP;
5100 END IF;
5101 ELSE
5102
5103 --Bug #4681261 - with re-using of temporary tables, we cannot use stored generated names
5104 --anymore because these names depend not only on ps_node_id, model_ref_expl_id but also
5105 --on where the rule is assined. Name will be generated in generate_argument.
5106 --nodeName := GENERATE_NAME(nChild, v_tExprPsNodeId(nChild));
5107
5108 v_return(nCount).node_type := DATA_TYPE_NODE;
5109 v_return(nCount).node_value := NULL;
5110 v_return(nCount).node_id := v_tExprPsNodeId(nChild);
5111 v_return(nCount).node_obj := NULL;
5112 v_return(nCount).node_id_ex := v_tExplNodeId(nChild);
5113 END IF;
5114 ELSIF(v_tExprType(nChild) = EXPR_LITERAL)THEN
5115
5116 v_return(nCount).node_type := v_tExprDataType(nChild);
5117 v_return(nCount).node_value := v_tExprDataValue(nChild);
5118 v_return(nCount).node_id := NULL;
5119 v_return(nCount).node_obj := NULL;
5120
5121 ELSIF(v_tExprType(nChild) = EXPR_OPERATOR AND v_tExprSubtype(nChild) = OPERATOR_OPTIONSOF)THEN
5122
5123 nGrand := v_ChildrenIndex(v_tExprId(nChild));
5124
5125 IF(v_NumberOfChildren(v_tExprId(j)) = 1)THEN
5126
5127 temp_table_hash_key(forallLevel) := TO_CHAR(v_tExprPsNodeId(nGrand)) || '-' || TO_CHAR(v_tExplNodeId(nGrand));
5128 temp_cmpt_hash_key(compatLevel) := temp_table_hash_key(forallLevel);
5129 END IF;
5130
5131 v_result := EXPAND_NODE(nChild);
5132
5133 FOR i IN 1..v_result.COUNT LOOP
5134
5135 --Bug #4681261 - with re-using of temporary tables, we cannot use stored generated names
5136 --anymore because these names depend not only on ps_node_id, model_ref_expl_id but also
5137 --on where the rule is assined. Name will be generated in generate_argument.
5138 --nodeName := GENERATE_NAME_EXPL(v_ExplByPsNodeId(v_result(i)), v_result(i));
5139
5140 v_return(nCount).node_type := DATA_TYPE_NODE;
5141 v_return(nCount).node_value := NULL;
5142 v_return(nCount).node_id := v_result(i);
5143 v_return(nCount).node_obj := NULL;
5144 v_return(nCount).node_id_ex := v_ExplByPsNodeId(v_result(i));
5145
5146 nCount := nCount + 1;
5147 END LOOP;
5148
5149 ELSIF(v_tExprType(nChild) IN (EXPR_FORALL, EXPR_FORALL_DISTINCT))THEN
5150
5151 v_iterin := GENERATE_FORALL(nChild, ListType);
5152
5153 FOR i IN 1..v_iterin.COUNT LOOP
5154
5155 v_return(nCount) := v_iterin(i);
5156 nCount := nCount + 1;
5157 END LOOP;
5158 ELSE
5159
5160 v_record := GENERATE_EXPRESSION(nChild, ListType);
5161
5162 IF(v_tExprPsNodeId(nChild) IS NOT NULL)THEN
5163
5164 nType := v_tExprType(nChild);
5165 v_tExprType(nChild) := EXPR_PSNODE;
5166
5167 v_iterin := GENERATE_ITERATOR(j, ListType);
5168 v_tExprType(nChild) := nType;
5169
5170 FOR i IN 1..v_iterin.COUNT LOOP
5171
5172 v_return(nCount) := v_iterin(i);
5173 nCount := nCount + 1;
5174 END LOOP;
5175
5176 ELSE
5177
5178 FOR i IN 1..v_record.COUNT LOOP
5179
5180 v_return(nCount).node_type := DATA_TYPE_VARIANT;
5181 v_return(nCount).node_value := v_record(i);
5182
5183 --If it's a 'P_' object, the node_id should still be populated, otherwise it will be impossible
5184 --to use properties of this objects.
5185
5186 v_return(nCount).node_id := NULL;
5187 v_return(nCount).node_obj := v_record(i);
5188
5189 nCount := nCount + 1;
5190 END LOOP;
5191 END IF;
5192 END IF;
5193
5194 nChild := nChild + 1;
5195 END LOOP;
5196
5197 nDebug := 7004009;
5198
5199 RETURN v_return;
5200 END;
5201 ---------------------------------------------------------------------------------------
5202 FUNCTION EXTRACT_PROPERTY_INFO(j IN PLS_INTEGER, PropName OUT NOCOPY VARCHAR2,
5203 DataType OUT NOCOPY PLS_INTEGER,
5204 PropertyType OUT NOCOPY PLS_INTEGER)
5205 RETURN PLS_INTEGER IS
5206 propChild PLS_INTEGER := v_ChildrenIndex(v_tExprId(j));
5207 propertyId PLS_INTEGER;
5208 tempVal NUMBER := -1;
5209 BEGIN
5210
5211 nDebug := 7004040;
5212
5213 PropertyType := 0;
5214
5215 WHILE(v_tExprParentId(propChild) = v_tExprId(j) AND
5216 v_tExprPropertyId(propChild) IS NULL AND v_tExprType(propChild) NOT IN
5217 (EXPR_NODE_TYPE_SYSPROP, EXPR_LITERAL))LOOP
5218 propChild := propChild + 1;
5219 END LOOP;
5220
5221 nDebug := 7004042;
5222
5223 IF(v_tExprParentId(propChild) = v_tExprId(j))THEN
5224 BEGIN
5225 IF(v_tExprPropertyId(propChild) IS NOT NULL)THEN
5226
5227 SELECT data_type, name INTO DataType, PropName
5228 FROM cz_properties
5229 WHERE deleted_flag = FLAG_NOT_DELETED
5230 AND property_id = v_tExprPropertyId(propChild);
5231 nDebug := 7004043;
5232
5233 RETURN v_tExprPropertyId(propChild);
5234
5235 ELSIF(v_tExprType(propChild) = EXPR_LITERAL)THEN
5236
5237 SELECT property_id, data_type, name INTO propertyId, DataType, PropName
5238 FROM cz_properties
5239 WHERE deleted_flag = FLAG_NOT_DELETED
5240 AND name = v_tExprDataValue(propChild);
5241
5242 RETURN propertyId;
5243 ELSE
5244
5245 PropertyType := 1;
5246 WHILE(v_tExprParentId(propChild) = v_tExprId(j) AND
5247 h_SeededName(v_tExprSubtype(propChild)) = RULE_SYS_PROP_PARENT)LOOP
5248
5249 propChild := propChild + 1;
5250 PropertyType := PropertyType + 1;
5251 END LOOP;
5252 IF(v_tExprParentId(propChild) = v_tExprId(j))THEN
5253
5254 SELECT data_type, name INTO DataType, PropName
5255 FROM cz_system_properties_v
5256 WHERE rule_id = v_tExprSubtype(propChild);
5257
5258 RETURN v_tExprSubtype(propChild);
5259 ELSE
5260 RAISE CZ_E_INCORRECT_PROPERTY;
5261 END IF;
5262 END IF;
5263 EXCEPTION
5264 WHEN OTHERS THEN
5265 RAISE CZ_E_INCORRECT_PROPERTY;
5266 END;
5267 ELSE
5268 RAISE CZ_E_INCORRECT_PROPERTY;
5269 END IF;
5270 nDebug := 7004049;
5271 END;
5272 ---------------------------------------------------------------------------------------
5273 FUNCTION GENERATE_FORALL_(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tIteratorArray IS
5274
5275 iteratorIndex tIntegerArray;
5276 iterator tIteratorArray;
5277 whereIndex PLS_INTEGER := 0;
5278 expressionIndex PLS_INTEGER := 0;
5279 nChild PLS_INTEGER;
5280 nCount PLS_INTEGER;
5281 v_property_id tIntegerArray;
5282 v_data_type tIntegerArray;
5283 v_prop_name tStringArray;
5284 v_return tIteratorArray;
5285 v_express tStringArray;
5286 SQLCreate VARCHAR2(8000);
5287 SQLInsert VARCHAR2(8000);
5288 SQLValues VARCHAR2(8000);
5289 SQLSelect VARCHAR2(8000);
5290 SQLFrom VARCHAR2(8000);
5291 SQLWhere VARCHAR2(8000) := NULL;
5292 tableName VARCHAR2(4000);
5293 tableAlias VARCHAR2(4000);
5294 nodeId NUMBER; --jonatara:bug7041718
5295 itemId PLS_INTEGER;
5296 propertyId PLS_INTEGER;
5297 c_values refCursor;
5298 v_cursor NUMBER;
5299 propertyVal VARCHAR2(4000);
5300 localNumber NUMBER;
5301 localString VARCHAR2(4000);
5302 bindValue tStringArray;
5303 v_flag tIntegerArray;
5304 v_stack_start PLS_INTEGER;
5305 v_stack_end PLS_INTEGER;
5306 v_value_exists PLS_INTEGER := 0;
5307
5308 bind_node_id DBMS_SQL.NUMBER_TABLE;
5309 bind_node_id_ex DBMS_SQL.NUMBER_TABLE;
5310 bind_node_type DBMS_SQL.NUMBER_TABLE;
5311 bind_node_value DBMS_SQL.VARCHAR2_TABLE;
5312 bind_node_obj DBMS_SQL.VARCHAR2_TABLE;
5313
5314 TYPE bind_value_table IS TABLE OF DBMS_SQL.VARCHAR2_TABLE INDEX BY BINARY_INTEGER;
5315 bind_values bind_value_table;
5316 arg_table_name temp_table_hash_type;
5317 hash_propval_key VARCHAR2(4000);
5318 ---------------------------------------------------------------------------------------
5319 PROCEDURE EXPLORE_WHERE(j IN PLS_INTEGER, v_argument IN VARCHAR2) IS
5320 nChild PLS_INTEGER;
5321 nCount PLS_INTEGER;
5322 propertyId PLS_INTEGER;
5323 dataType PLS_INTEGER;
5324 propType PLS_INTEGER;
5325 propName cz_properties.name%TYPE;
5326 BEGIN
5327
5328 nDebug := 7004020;
5329
5330 nChild := v_ChildrenIndex(v_tExprId(j));
5331
5332 WHILE(v_tExprParentId(nChild) = v_tExprId(j))LOOP
5333
5334 nCount := v_property_id.COUNT + 1;
5335
5336 IF(v_ChildrenIndex.EXISTS(v_tExprId(nChild)))THEN
5337 IF(v_tExprType(nChild) = EXPR_ARGUMENT AND v_tExprArgumentName(nChild) = v_argument)THEN
5338
5339 propertyId := EXTRACT_PROPERTY_INFO(nChild, propName, dataType, propType);
5340
5341 nDebug := 7004021;
5342
5343 IF(NOT v_flag.EXISTS(propertyId))THEN
5344
5345 v_property_id(nCount) := propertyId;
5346 v_data_type(nCount) := dataType;
5347 v_prop_name(nCount) := propName;
5348 v_flag(propertyId) := propType;
5349 END IF;
5350 ELSE
5351
5352 EXPLORE_WHERE(nChild, v_argument);
5353 END IF;
5354 END IF;
5355 nChild := nChild + 1;
5356 END LOOP;
5357
5358 nDebug := 7004029;
5359 END;
5360 ---------------------------------------------------------------------------------------
5361 --This function finds every reference to iterators in the FORALL WHERE clause, replaces
5362 --arguments with <table_alias>.value string and reference nodes with <table_alias>.i_<property_id>
5363 --string. It returns the generated SQL WHERE clause of the SELECT statement. All the literal
5364 --values are collected in an array for later binding.
5365
5366 FUNCTION EXAMINE_WHERE_CLAUSE(j IN PLS_INTEGER) RETURN VARCHAR2 IS
5367 argChild PLS_INTEGER;
5368 propType PLS_INTEGER;
5369 jChild PLS_INTEGER;
5370 isLocal PLS_INTEGER := 0;
5371 LocalType PLS_INTEGER := DATA_TYPE_VOID;
5372 propName cz_properties.name%TYPE;
5373 v_extern tStringArray;
5374 v_quotes VARCHAR2(2);
5375 BEGIN
5376
5377 nDebug := 7004030;
5378
5379 IF(v_tExprType(j) = EXPR_ARGUMENT)THEN
5380
5381 --This is an argument. First of all, find out if it corresponds to one of the local iterators - only
5382 --in this case there will be a temporary table with the corresponding name. Otherwise, it can be an
5383 --external argument from an upper level FORALL. In this case we have to get the value from the
5384 --parameter scope and use it as a literal in the generated WHERE clause.
5385
5386 FOR i IN 1..iteratorIndex.COUNT LOOP
5387
5388 IF(v_tExprArgumentName(iteratorIndex(i)) = v_tExprArgumentName(j))THEN isLocal := 1; END IF;
5389 END LOOP;
5390
5391 IF(isLocal = 1)THEN
5392
5393 --This is an argument that corresponds to a local iterator.
5394
5395 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
5396
5397 --Add <table_name>.value to the WHERE clause being generated.
5398
5399 RETURN arg_table_name(v_tExprArgumentName(j)) || '.node_value';
5400 ELSE
5401
5402 --Add <table_name>.i_<property_id> to the WHERE clause being generated.
5403 RETURN arg_table_name(v_tExprArgumentName(j)) || '.i_' ||
5404 TO_CHAR(EXTRACT_PROPERTY_INFO(j, propName, jChild, propType));
5405 END IF;
5406 ELSE
5407
5408 --This is an external argument, must be in the parameter scope.
5409 --We assume that it is of type 'node'.
5410
5411 v_extern := GENERATE_ARGUMENT(j, LocalType);
5412 IF(LocalType = DATA_TYPE_TEXT)THEN v_quotes := ''''; END IF;
5413
5414 IF(v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
5415
5416 RETURN v_quotes || PROPERTY_VALUE(v_ChildrenIndex(v_tExprId(j)), glIndexByPsNodeId(v_tExprPsNodeId(j)), LocalType) || v_quotes;
5417 ELSE
5418
5419 RETURN v_quotes || v_extern(1) || v_quotes;
5420 END IF;
5421 END IF;
5422 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_NODE AND v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
5423
5424 --Nodes can participate in the WHERE clause only with a property applied.
5425 --Bug #4648386.
5426
5427 v_extern(1) := EXTRACT_PROPERTY_INFO(j, propName, jChild, propType);
5428 nDebug := 7004032;
5429 IF(jChild IN (DATATYPE_TRANSLATABLE_PROP, DATA_TYPE_TEXT))THEN v_quotes := ''''; END IF;
5430
5431 IF(propType = 0)THEN
5432
5433 RETURN v_quotes || PROPERTY_VALUE(v_ChildrenIndex(v_tExprId(j)), glIndexByPsNodeId(v_tExprPsNodeId(j)), LocalType) || v_quotes;
5434 ELSE
5435
5436 RETURN v_quotes || STATIC_SYSPROP_VALUE(v_tExprPsNodeId(j), v_tExprPropertyId(j), propType) || v_quotes;
5437 END IF;
5438 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_LITERAL)THEN
5439
5440 bindValue(bindValue.COUNT + 1) := v_tExprDataValue(j);
5441 RETURN ':x' || TO_CHAR(bindValue.COUNT);
5442
5443 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_OPERATOR)THEN
5444
5445 jChild := v_ChildrenIndex(v_tExprId(j));
5446
5447 IF(v_tExprSubtype(j) = OPERATOR_TOTEXT)THEN
5448
5449 --Added for the bug #5620750. Just need ignore the ToText operator to continue using
5450 --default type conversion.
5451
5452 RETURN EXAMINE_WHERE_CLAUSE(jChild);
5453 END IF;
5454
5455 IF(v_tExprParentId.EXISTS(jChild + 1) AND v_tExprParentId(jChild + 1)= v_tExprId(j))THEN
5456
5457 IF(v_tExprSubtype(j) IN (OPERATOR_EQUALS,
5458 OPERATOR_NOTEQUALS,
5459 OPERATOR_EQUALS_INT,
5460 OPERATOR_NOTEQUALS_INT,
5461 OPERATOR_GT,
5462 OPERATOR_LT,
5463 OPERATOR_GE,
5464 OPERATOR_LE,
5465 OPERATOR_AND,
5466 OPERATOR_OR))THEN
5467
5468 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || OperatorLiterals(v_tExprSubtype(j)) ||
5469 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
5470
5471 ELSIF(v_tExprSubtype(j) = OPERATOR_CONCAT)THEN
5472
5473 RETURN EXAMINE_WHERE_CLAUSE(jChild) || ' || ' || EXAMINE_WHERE_CLAUSE(jChild + 1);
5474
5475 ELSIF(v_tExprSubtype(j) = OPERATOR_BEGINSWITH)THEN
5476
5477 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ' ||
5478 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
5479
5480 ELSIF(v_tExprSubtype(j) = OPERATOR_ENDSWITH)THEN
5481
5482 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ''%'' || ' ||
5483 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
5484
5485 ELSIF(v_tExprSubtype(j) = OPERATOR_CONTAINS)THEN
5486
5487 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ''%'' || ' ||
5488 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
5489
5490 ELSIF(v_tExprSubtype(j) = OPERATOR_LIKE)THEN
5491
5492 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ' ||
5493 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
5494
5495 ELSIF(v_tExprSubtype(j) = OPERATOR_MATCHES)THEN
5496
5497 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ' ||
5498 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
5499
5500 ELSIF(v_tExprSubtype(j) = OPERATOR_DOESNOTBEGINWITH)THEN
5501
5502 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ' ||
5503 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
5504
5505 ELSIF(v_tExprSubtype(j) = OPERATOR_DOESNOTENDWITH)THEN
5506
5507 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ''%'' || ' ||
5508 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
5509
5510 ELSIF(v_tExprSubtype(j) = OPERATOR_DOESNOTCONTAIN)THEN
5511
5512 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ''%'' || ' ||
5513 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
5514
5515 ELSIF(v_tExprSubtype(j) = OPERATOR_NOTLIKE)THEN
5516
5517 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ' ||
5518 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
5519
5520 ELSE
5521
5522 RAISE CZ_E_UKNOWN_OPER_IN_COMPAT;
5523 END IF;
5524
5525 ELSIF(v_tExprSubtype(j) = OPERATOR_NOT)THEN
5526
5527 RETURN '(NOT ' || EXAMINE_WHERE_CLAUSE(jChild) || ')';
5528
5529 ELSE
5530
5531 RAISE CZ_E_WRONG_OPER_IN_COMPAT;
5532 END IF;
5533 ELSE
5534
5535 RAISE CZ_R_WRONG_COMPAT_EXPRESSION;
5536 END IF;
5537 END;
5538 ---------------------------------------------------------------------------------------
5539 BEGIN
5540
5541 nDebug := 7004100;
5542
5543 nChild := v_ChildrenIndex(v_tExprId(j));
5544
5545 WHILE(v_tExprParentId(nChild) = v_tExprId(j)) LOOP
5546 IF(v_tExprType(nChild) = EXPR_ITERATOR)THEN
5547
5548 iteratorIndex(iteratorIndex.COUNT + 1) := nChild;
5549 ELSIF(v_tExprType(nChild) = EXPR_WHERE)THEN
5550
5551 whereIndex := nChild;
5552 ELSE
5553
5554 expressionIndex := nChild;
5555 END IF;
5556
5557 nChild := nChild + 1;
5558 END LOOP;
5559
5560 v_stack_start := parameterScope.COUNT + 1;
5561 v_stack_end := v_stack_start + iteratorIndex.COUNT - 1;
5562
5563 nDebug := 7004101;
5564
5565 FOR i IN 1..iteratorIndex.COUNT LOOP
5566
5567 bind_node_id.DELETE;
5568 bind_node_id_ex.DELETE;
5569 bind_node_type.DELETE;
5570 bind_node_value.DELETE;
5571 bind_node_obj.DELETE;
5572 bind_values.DELETE;
5573
5574 v_property_id.DELETE;
5575 v_data_type.DELETE;
5576 v_prop_name.DELETE;
5577 v_flag.DELETE;
5578
5579 temp_table_hash_key(forallLevel) := NULL;
5580 tableAlias := 'T' || TO_CHAR(i);
5581
5582 iterator.DELETE;
5583 iterator := GENERATE_ITERATOR(iteratorIndex(i), ListType);
5584
5585 IF(whereIndex <> 0)THEN
5586 EXPLORE_WHERE(whereIndex, v_tExprArgumentName(iteratorIndex(i)));
5587 END IF;
5588
5589 IF(temp_table_hash_key(forallLevel) IS NOT NULL)THEN
5590 FOR ii IN 1..v_property_id.COUNT LOOP
5591 temp_table_hash_key(forallLevel) := temp_table_hash_key(forallLevel) || '-' || TO_CHAR(v_property_id(ii));
5592 END LOOP;
5593 END IF;
5594
5595 nDebug := 7004102;
5596
5597 IF(temp_table_hash_key(forallLevel) IS NOT NULL AND temp_table_hash.EXISTS(temp_table_hash_key(forallLevel)))THEN
5598
5599 tableName := temp_table_hash(temp_table_hash_key(forallLevel));
5600 arg_table_name(v_tExprArgumentName(iteratorIndex(i))) := tableAlias;
5601
5602 IF(SQLSelect IS NULL)THEN SQLSelect := 'SELECT '; ELSE SQLSelect := SQLSelect || ', '; END IF;
5603 SQLSelect := SQLSelect || tableAlias || '.node_type, ' ||
5604 tableAlias || '.node_id, ' ||
5605 tableAlias || '.node_value, ' ||
5606 tableAlias || '.node_obj, ' ||
5607 tableAlias || '.node_id_ex';
5608 IF(SQLFrom IS NULL)THEN SQLFrom := ' FROM '; ELSE SQLFrom := SQLFrom || ', '; END IF;
5609 SQLFrom := SQLFrom || tableName || ' ' || tableAlias;
5610
5611 ELSE
5612
5613 tableName := 'G_' || TO_CHAR(table_name_generator);
5614 table_name_generator := table_name_generator + 1;
5615 arg_table_name(v_tExprArgumentName(iteratorIndex(i))) := tableAlias;
5616
5617 IF(SQLSelect IS NULL)THEN SQLSelect := 'SELECT '; ELSE SQLSelect := SQLSelect || ', '; END IF;
5618 SQLSelect := SQLSelect || tableAlias || '.node_type, ' ||
5619 tableAlias || '.node_id, ' ||
5620 tableAlias || '.node_value, ' ||
5621 tableAlias || '.node_obj, ' ||
5622 tableAlias || '.node_id_ex';
5623 IF(SQLFrom IS NULL)THEN SQLFrom := ' FROM '; ELSE SQLFrom := SQLFrom || ', '; END IF;
5624 SQLFrom := SQLFrom || tableName || ' ' || tableAlias;
5625
5626 SQLCreate := 'CREATE GLOBAL TEMPORARY TABLE ' || tableName ||
5627 '(node_type NUMBER, node_id NUMBER, node_value VARCHAR2(' || TO_CHAR(MAXIMUM_INDEX_LENGTH) ||
5628 '), node_obj VARCHAR2(' || TO_CHAR(MAXIMUM_INDEX_LENGTH) || '), node_id_ex NUMBER';
5629
5630 FOR ii IN 1..v_property_id.COUNT LOOP
5631
5632 SQLCreate := SQLCreate || ', i_' || TO_CHAR(v_property_id(ii));
5633
5634 IF(v_data_type(ii) IN (DATA_TYPE_INTEGER, DATA_TYPE_DECIMAL))THEN
5635
5636 SQLCreate := SQLCreate || ' NUMBER';
5637 ELSE
5638
5639 SQLCreate := SQLCreate || ' VARCHAR2(' || TO_CHAR(MAXIMUM_INDEX_LENGTH) || ')';
5640 END IF;
5641 END LOOP;
5642
5643 SQLCreate := SQLCreate || ') ON COMMIT PRESERVE ROWS';
5644
5645 nDebug := 7004103;
5646
5647 BEGIN
5648 EXECUTE IMMEDIATE SQLCreate;
5649 EXCEPTION
5650 WHEN OTHERS THEN
5651
5652 --If the table already exists, truncate it, drop and try to create again.
5653
5654 IF(SQLCODE = ORACLE_OBJECT_ALREADY_EXISTS)THEN
5655 EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || tableName;
5656 EXECUTE IMMEDIATE 'DROP TABLE ' || tableName;
5657 EXECUTE IMMEDIATE SQLCreate;
5658 ELSE
5659 RAISE;
5660 END IF;
5661 END;
5662
5663 --The table is created, add its name to the delete list.
5664
5665 temp_tables(temp_tables.COUNT + 1) := tableName;
5666
5667 nDebug := 7004104;
5668
5669 SQLInsert := 'INSERT INTO ' || tableName || '(node_type, node_id, node_value, node_obj, node_id_ex';
5670 SQLValues := ' VALUES (:y1, :y2, :y3, :y4, :y5';
5671
5672 FOR ii IN 1..v_property_id.COUNT LOOP
5673
5674 BEGIN
5675
5676 EXECUTE IMMEDIATE 'CREATE INDEX ' || tableName || '_I' || TO_CHAR(ii) || ' ON ' || tableName ||
5677 '(i_' || v_property_id(ii) || ')';
5678 EXCEPTION
5679 WHEN OTHERS THEN
5680 IF(SQLCODE <> ORACLE_OBJECT_ALREADY_EXISTS)THEN RAISE; END IF;
5681 END;
5682
5683 SQLInsert := SQLInsert || ', i_' || TO_CHAR(v_property_id(ii));
5684 SQLValues := SQLValues || ', :x' || TO_CHAR(ii);
5685 END LOOP;
5686
5687 SQLInsert := SQLInsert || ')';
5688 SQLValues := SQLValues || ')';
5689
5690 nDebug := 7004105;
5691
5692 FOR ii IN 1..iterator.COUNT LOOP
5693
5694 IF(LENGTH(iterator(ii).node_value) > MAXIMUM_INDEX_LENGTH OR
5695 LENGTH(iterator(ii).node_obj) > MAXIMUM_INDEX_LENGTH)THEN
5696
5697 --Bug #3416994. This structure is internally generated, so we give the 'internal error' message.
5698 RAISE CZ_R_TYPE_NO_PROPERTY;
5699 END IF;
5700
5701 bind_node_id(ii) := iterator(ii).node_id;
5702 bind_node_id_ex(ii) := iterator(ii).node_id_ex;
5703 bind_node_value(ii) := iterator(ii).node_value;
5704 bind_node_obj(ii) := iterator(ii).node_obj;
5705 bind_node_type(ii) := iterator(ii).node_type;
5706
5707 IF(v_property_id.COUNT > 0)THEN
5708
5709 --This is only valid if there are properties.
5710
5711 IF(iterator(ii).node_id IS NULL)THEN RAISE CZ_R_TYPE_NO_PROPERTY; END IF;
5712
5713 nodeId := glPsNodeId(glIndexByPsNodeId(iterator(ii).node_id));
5714 itemId := glItemId(glIndexByPsNodeId(iterator(ii).node_id));
5715 END IF;
5716
5717 --Get the property values and insert the data.
5718
5719 FOR jj IN 1..v_property_id.COUNT LOOP
5720
5721 propertyId := v_property_id(jj);
5722 hash_propval_key := TO_CHAR(nodeId) || '-' || TO_CHAR(itemId) || '-' ||
5723 TO_CHAR(propertyId) || '-' || TO_CHAR(v_flag(propertyId));
5724
5725 IF(NOT table_hash_propval.EXISTS(hash_propval_key))THEN
5726
5727 IF(v_flag(propertyId) = 0)THEN
5728
5729 --User property.
5730
5731 propertyVal := GET_PROPERTY_VALUE(nodeId, propertyId, itemId, localNumber);
5732
5733 --Bug #4554100.
5734
5735 IF(localNumber IS NULL)THEN
5736
5737 errorMessage := v_prop_name(jj);
5738 auxIndex := glIndexByPsNodeId(iterator(ii).node_id);
5739 IF(glParentId(auxIndex) IS NULL)THEN nParam := auxIndex; ELSE
5740 nParam := glIndexByPsNodeId(glParentId(auxIndex)); END IF;
5741 RAISE CZ_R_OPTION_NO_PROPERTY;
5742 END IF;
5743 ELSE
5744
5745 --System property.
5746
5747 propertyVal := STATIC_SYSPROP_VALUE(nodeId, propertyId, v_flag(v_property_id(jj)));
5748 END IF;
5749
5750 IF(LENGTH(propertyVal) > MAXIMUM_INDEX_LENGTH)THEN
5751
5752 --Bug #3416994.
5753
5754 errorMessage := v_prop_name(jj);
5755 auxIndex := glIndexByPsNodeId(iterator(ii).node_id);
5756 IF(glParentId(auxIndex) IS NULL)THEN nParam := auxIndex; ELSE
5757 nParam := glIndexByPsNodeId(glParentId(auxIndex)); END IF;
5758 RAISE CZ_R_LONG_PROPERTY_VALUE;
5759 END IF;
5760
5761 bind_values(jj)(ii) := propertyVal;
5762 table_hash_propval(hash_propval_key) := propertyVal;
5763 ELSE
5764 bind_values(jj)(ii) := table_hash_propval(hash_propval_key);
5765 END IF;
5766 END LOOP;
5767 END LOOP;
5768
5769 nDebug := 7004106;
5770
5771 v_cursor := DBMS_SQL.OPEN_CURSOR;
5772 DBMS_SQL.PARSE(v_cursor, SQLInsert || SQLValues, DBMS_SQL.NATIVE);
5773
5774 DBMS_SQL.BIND_ARRAY(v_cursor, ':y1', bind_node_type);
5775 DBMS_SQL.BIND_ARRAY(v_cursor, ':y2', bind_node_id);
5776 DBMS_SQL.BIND_ARRAY(v_cursor, ':y3', bind_node_value);
5777 DBMS_SQL.BIND_ARRAY(v_cursor, ':y4', bind_node_obj);
5778 DBMS_SQL.BIND_ARRAY(v_cursor, ':y5', bind_node_id_ex);
5779
5780 FOR ii IN 1..v_property_id.COUNT LOOP
5781 DBMS_SQL.BIND_ARRAY(v_cursor, ':x' || TO_CHAR(ii), bind_values(ii));
5782 END LOOP;
5783
5784 localNumber := DBMS_SQL.EXECUTE(v_cursor);
5785 DBMS_SQL.CLOSE_CURSOR(v_cursor);
5786
5787 nDebug := 7004107;
5788
5789 EXECUTE IMMEDIATE 'ANALYZE TABLE ' || tableName || ' COMPUTE STATISTICS';
5790
5791 --The table is created and populated, add its name to the hash for re-use if it is eligible.
5792
5793 IF(temp_table_hash_key(forallLevel) IS NOT NULL)THEN temp_table_hash(temp_table_hash_key(forallLevel)) := tableName; END IF;
5794 END IF;
5795 END LOOP;
5796
5797 --Generate the WHERE clause and run the query with bind variables. For every row returned,
5798 --generate the expression and return the object.
5799 --To do this, add GENERATE_ARGUMENT to the GENERATE_EXPRESSION.
5800
5801 nDebug := 7004108;
5802
5803 IF(whereIndex <> 0)THEN
5804
5805 SQLWhere := ' WHERE ' || EXAMINE_WHERE_CLAUSE(v_ChildrenIndex(v_tExprId(whereIndex)));
5806 END IF;
5807
5808 v_cursor := DBMS_SQL.OPEN_CURSOR;
5809 DBMS_SQL.PARSE(v_cursor, SQLSelect || SQLFrom || SQLWhere, DBMS_SQL.NATIVE);
5810
5811 FOR i IN 1..bindValue.COUNT LOOP
5812 DBMS_SQL.BIND_VARIABLE(v_cursor, ':x' || TO_CHAR(i), bindValue(i));
5813 END LOOP;
5814
5815 FOR i IN 1..iteratorIndex.COUNT LOOP
5816
5817 DBMS_SQL.DEFINE_COLUMN(v_cursor, 5 * (i - 1) + 1, localNumber);
5818 DBMS_SQL.DEFINE_COLUMN(v_cursor, 5 * (i - 1) + 2, localNumber);
5819 DBMS_SQL.DEFINE_COLUMN(v_cursor, 5 * (i - 1) + 3, localString, 2000);
5820 DBMS_SQL.DEFINE_COLUMN(v_cursor, 5 * (i - 1) + 4, localString, 2000);
5821 DBMS_SQL.DEFINE_COLUMN(v_cursor, 5 * (i - 1) + 5, localNumber);
5822 END LOOP;
5823
5824 nDebug := 7004109;
5825
5826 localNumber := DBMS_SQL.EXECUTE(v_cursor);
5827
5828 --For every returned row, store the values in the parameter scope, from where GENERATE_EXPRESSION
5829 --will be retrieving it when generating an argument.
5830
5831 FOR i IN 1..iteratorIndex.COUNT LOOP
5832
5833 parameterName(v_stack_start + i - 1) := v_tExprArgumentName(iteratorIndex(i));
5834 END LOOP;
5835
5836 WHILE(DBMS_SQL.FETCH_ROWS(v_cursor) > 0)LOOP
5837
5838 FOR i IN 1..iteratorIndex.COUNT LOOP
5839
5840 DBMS_SQL.COLUMN_VALUE(v_cursor, 5 * (i - 1) + 1, parameterScope(v_stack_start + i - 1).node_type);
5841 DBMS_SQL.COLUMN_VALUE(v_cursor, 5 * (i - 1) + 2, parameterScope(v_stack_start + i - 1).node_id);
5842 DBMS_SQL.COLUMN_VALUE(v_cursor, 5 * (i - 1) + 3, parameterScope(v_stack_start + i - 1).node_value);
5843 DBMS_SQL.COLUMN_VALUE(v_cursor, 5 * (i - 1) + 4, parameterScope(v_stack_start + i - 1).node_obj);
5844 DBMS_SQL.COLUMN_VALUE(v_cursor, 5 * (i - 1) + 5, parameterScope(v_stack_start + i - 1).node_id_ex);
5845 END LOOP;
5846
5847 IF(expressionIndex <> 0 AND v_ChildrenIndex.EXISTS(v_tExprId(expressionIndex)))THEN
5848
5849 --Bug #5497235. This is a FORALL with an expression, need to generate the expression.
5850
5851 generateCollect := 1;
5852
5853 v_express := GENERATE_EXPRESSION(expressionIndex, ListType);
5854 generateCollect := 0;
5855
5856 nCount := v_return.COUNT + 1;
5857
5858 FOR i IN 1..v_express.COUNT LOOP
5859
5860 IF(v_tExprType(j) = EXPR_FORALL_DISTINCT)THEN
5861
5862 --For COLLECT DISTINCT we need to leave only distinct values in the results.
5863
5864 v_value_exists := 0;
5865
5866 FOR ii IN 1..nCount - 1 LOOP
5867 IF(v_return(ii).node_value = v_express(i))THEN v_value_exists := 1; EXIT; END IF;
5868 END LOOP;
5869 END IF;
5870
5871 IF(v_value_exists = 0)THEN
5872
5873 v_return(nCount).node_obj := v_express(i);
5874 v_return(nCount).node_value := v_express(i);
5875 v_return(nCount).node_id := NULL;
5876 v_return(nCount).node_type := DATA_TYPE_VARIANT;
5877 nCount := nCount + 1;
5878 END IF;
5879 END LOOP;
5880
5881 ELSE
5882
5883 --Bug #5497235. This is a COLLECT because there is no expression or the expression is just an argument.
5884 --In this case we need a direct copy of the parameter scope.
5885
5886 nCount := v_return.COUNT + 1;
5887
5888 /* Changing this for loop from 1..parameterscope.count to the below as part of the fix for the bug : 6355526*/
5889
5890 FOR i IN v_stack_start..v_stack_end LOOP
5891
5892
5893 v_return(nCount).node_id := parameterScope(i).node_id;
5894 v_return(nCount).node_type := parameterScope(i).node_type;
5895 v_return(nCount).node_value := parameterScope(i).node_value;
5896 v_return(nCount).node_obj := parameterScope(i).node_obj;
5897 v_return(nCount).node_id_ex := parameterScope(i).node_id_ex;
5898 nCount := nCount + 1;
5899 END LOOP;
5900 END IF;
5901 END LOOP;
5902
5903 parameterScope.DELETE(v_stack_start, v_stack_end);
5904 parameterName.DELETE(v_stack_start, v_stack_end);
5905
5906 nDebug := 7004110;
5907
5908 DBMS_SQL.CLOSE_CURSOR(v_cursor);
5909
5910 IF(v_tExprParentId(j) IS NOT NULL AND v_return.COUNT = 0)THEN
5911
5912 --The FORALL or COLLECT did not yield any rows while it is not the root operator.
5913 --Need a new message to report this.
5914
5915 RAISE CZ_R_COMPAT_NO_COMBINATIONS;
5916 END IF;
5917
5918 RETURN v_return;
5919 END;
5920 ---------------------------------------------------------------------------------------
5921 --This function is introduced to support the level of embedding.
5922
5923 FUNCTION GENERATE_FORALL(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tIteratorArray IS
5924 v_return tIteratorArray;
5925 BEGIN
5926 forallLevel := forallLevel + 1;
5927 v_return := GENERATE_FORALL_(j, ListType);
5928 forallLevel := forallLevel - 1;
5929 RETURN v_return;
5930 EXCEPTION
5931 WHEN OTHERS THEN
5932 forallLevel := forallLevel - 1;
5933 RAISE;
5934 END;
5935 ---------------------------------------------------------------------------------------
5936 FUNCTION GENERATE_COMPATIBLE_(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
5937
5938 iteratorIndex tIntegerArray;
5939 iterator tIteratorArray;
5940 whereIndex PLS_INTEGER := 0;
5941 featureIndex PLS_INTEGER;
5942 nChild NUMBER; -- jonatara:bug7041718
5943 nCounter NUMBER; -- jonatara:bug7041718
5944 v_property_id tIntegerArray;
5945 v_data_type tIntegerArray;
5946 v_prop_name tStringArray;
5947 v_return tStringArray;
5948 SQLCreate VARCHAR2(8000);
5949 SQLInsert VARCHAR2(8000);
5950 SQLValues VARCHAR2(8000);
5951 SQLSelect VARCHAR2(8000);
5952 SQLFrom VARCHAR2(8000);
5953 SQLWhere VARCHAR2(8000) := NULL;
5954 tableName VARCHAR2(4000);
5955 tableAlias VARCHAR2(4000);
5956 nodeId NUMBER; -- jonatara:bug7041718
5957 itemId PLS_INTEGER;
5958 propertyId PLS_INTEGER;
5959 c_values refCursor;
5960 v_cursor NUMBER;
5961 propertyVal VARCHAR2(4000);
5962 localNumber NUMBER;
5963 localString VARCHAR2(4000);
5964 bindValue tStringArray;
5965 typeCheck NUMBER;
5966 v_tOptionId DBMS_SQL.NUMBER_TABLE;
5967 v_tFeatureId tExplNodeId;
5968 v_BackIndex tIntegerArray;
5969 v_tExplId tExplNodeId;
5970 rowThreshold PLS_INTEGER := 0;
5971 v_OptionExists tIntegerArray_idx_vc2; --kdande; Bug 6881902; 11-Mar-2008
5972 v_OptionsChain tIntegerArray;
5973 v_FeatureIndex tIntegerArray;
5974 v_ItemIndex tIntegerArray;
5975 chainIndex PLS_INTEGER := 1;
5976 currentIndex PLS_INTEGER;
5977 itemIndex PLS_INTEGER;
5978 itemCount PLS_INTEGER := 1;
5979 v_RowLines tStringArray;
5980 v_ItemLines tStringArray;
5981 ExcludesRequired PLS_INTEGER;
5982 v_flag tIntegerArray;
5983
5984 bind_node_id DBMS_SQL.NUMBER_TABLE;
5985
5986 TYPE bind_value_table IS TABLE OF DBMS_SQL.VARCHAR2_TABLE INDEX BY BINARY_INTEGER;
5987 bind_values bind_value_table;
5988 arg_table_name temp_table_hash_type;
5989
5990 h_OptionExplId table_of_tNumberArray_idx_vc2;-- jonatara:bug7041718
5991 hash_propval_key VARCHAR2(4000);
5992 ---------------------------------------------------------------------------------------
5993 PROCEDURE EXPLORE_WHERE(j IN PLS_INTEGER, v_argument IN VARCHAR2) IS
5994 nChild PLS_INTEGER;
5995 nCount PLS_INTEGER;
5996 propertyId PLS_INTEGER;
5997 dataType PLS_INTEGER;
5998 propType PLS_INTEGER;
5999 propName cz_properties.name%TYPE;
6000 BEGIN
6001
6002 nDebug := 7005020;
6003
6004 nChild := v_ChildrenIndex(v_tExprId(j));
6005
6006 WHILE(v_tExprParentId(nChild) = v_tExprId(j))LOOP
6007
6008 nCount := v_property_id.COUNT + 1;
6009
6010 IF(v_ChildrenIndex.EXISTS(v_tExprId(nChild)))THEN
6011 IF(v_tExprType(nChild) = EXPR_ARGUMENT AND v_tExprArgumentName(nChild) = v_argument)THEN
6012
6013 propertyId := EXTRACT_PROPERTY_INFO(nChild, propName, dataType, propType);
6014 nDebug := 7005021;
6015 IF(NOT v_flag.EXISTS(propertyId))THEN
6016
6017 v_property_id(nCount) := propertyId;
6018 v_data_type(nCount) := dataType;
6019 v_prop_name(nCount) := propName;
6020 v_flag(propertyId) := propType;
6021 END IF;
6022 ELSE
6023
6024 EXPLORE_WHERE(nChild, v_argument);
6025 END IF;
6026 END IF;
6027 nChild := nChild + 1;
6028 END LOOP;
6029
6030 nDebug := 7005029;
6031 END;
6032 ---------------------------------------------------------------------------------------
6033 --This function finds every reference to iterators in the FORALL WHERE clause, replaces
6034 --arguments with 'G_<argument_name>.value' string and reference nodes with
6035 --'G_<argument_name>.i_<property_id>' string. It returns the generated SQL
6036 --WHERE clause of the SELECT statement.
6037 --All the literal values are collected in an array for later binding.
6038
6039 FUNCTION EXAMINE_WHERE_CLAUSE(j IN PLS_INTEGER) RETURN VARCHAR2 IS
6040 argChild PLS_INTEGER;
6041 propType PLS_INTEGER;
6042 jChild PLS_INTEGER;
6043 propName cz_properties.name%TYPE;
6044 LocalType PLS_INTEGER := DATA_TYPE_VOID;
6045 v_extern tStringArray;
6046 v_quotes VARCHAR2(2);
6047 BEGIN
6048
6049 nDebug := 7005030;
6050
6051 IF(v_tExprType(j) = EXPR_ARGUMENT)THEN
6052 IF(NOT v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
6053
6054 --Add <table_name>.value to the WHERE clause being generated.
6055
6056 RETURN arg_table_name(v_tExprArgumentName(j)) || '.node_value';
6057 ELSE
6058
6059 --Add <table_name>.i_<property_id> to the WHERE clause being generated.
6060 RETURN arg_table_name(v_tExprArgumentName(j)) || '.i_' ||
6061 TO_CHAR(EXTRACT_PROPERTY_INFO(j, propName, jChild, propType));
6062 END IF;
6063 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_NODE AND v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
6064
6065 --Nodes can participate in the WHERE clause only with a property applied.
6066 --Bug #4648386.
6067
6068 v_extern(1) := EXTRACT_PROPERTY_INFO(j, propName, jChild, propType);
6069
6070 nDebug := 7005032;
6071
6072 IF(jChild IN (DATATYPE_TRANSLATABLE_PROP, DATA_TYPE_TEXT))THEN v_quotes := ''''; END IF;
6073
6074 IF(propType = 0)THEN
6075
6076 RETURN v_quotes || PROPERTY_VALUE(v_ChildrenIndex(v_tExprId(j)), glIndexByPsNodeId(v_tExprPsNodeId(j)), LocalType) || v_quotes;
6077 ELSE
6078
6079 RETURN v_quotes || STATIC_SYSPROP_VALUE(v_tExprPsNodeId(j), v_tExprPropertyId(j), propType) || v_quotes;
6080 END IF;
6081 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_LITERAL)THEN
6082
6083 bindValue(bindValue.COUNT + 1) := v_tExprDataValue(j);
6084 RETURN ':x' || TO_CHAR(bindValue.COUNT);
6085
6086 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_OPERATOR)THEN
6087
6088 jChild := v_ChildrenIndex(v_tExprId(j));
6089
6090 IF(v_tExprSubtype(j) = OPERATOR_TOTEXT)THEN
6091
6092 --Added for the bug #5620750. Just need to ignore the ToText operator to preserve the
6093 --default type conversion.
6094
6095 RETURN EXAMINE_WHERE_CLAUSE(jChild);
6096 END IF;
6097
6098 IF(v_tExprParentId.EXISTS(jChild + 1) AND v_tExprParentId(jChild + 1)= v_tExprId(j))THEN
6099
6100 IF(v_tExprSubtype(j) IN (OPERATOR_EQUALS,
6101 OPERATOR_NOTEQUALS,
6102 OPERATOR_EQUALS_INT,
6103 OPERATOR_NOTEQUALS_INT,
6104 OPERATOR_GT,
6105 OPERATOR_LT,
6106 OPERATOR_GE,
6107 OPERATOR_LE,
6108 OPERATOR_AND,
6109 OPERATOR_OR))THEN
6110
6111 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || OperatorLiterals(v_tExprSubtype(j)) ||
6112 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
6113
6114 ELSIF(v_tExprSubtype(j) = OPERATOR_CONCAT)THEN
6115
6116 RETURN EXAMINE_WHERE_CLAUSE(jChild) || ' || ' || EXAMINE_WHERE_CLAUSE(jChild + 1);
6117
6118 ELSIF(v_tExprSubtype(j) = OPERATOR_BEGINSWITH)THEN
6119
6120 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ' ||
6121 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
6122
6123 ELSIF(v_tExprSubtype(j) = OPERATOR_ENDSWITH)THEN
6124
6125 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ''%'' || ' ||
6126 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
6127
6128 ELSIF(v_tExprSubtype(j) = OPERATOR_CONTAINS)THEN
6129
6130 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ''%'' || ' ||
6131 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
6132
6133 ELSIF(v_tExprSubtype(j) = OPERATOR_LIKE)THEN
6134
6135 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ' ||
6136 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
6137
6138 ELSIF(v_tExprSubtype(j) = OPERATOR_MATCHES)THEN
6139
6140 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' LIKE ' ||
6141 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
6142
6143 ELSIF(v_tExprSubtype(j) = OPERATOR_DOESNOTBEGINWITH)THEN
6144
6145 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ' ||
6146 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
6147
6148 ELSIF(v_tExprSubtype(j) = OPERATOR_DOESNOTENDWITH)THEN
6149
6150 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ''%'' || ' ||
6151 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
6152
6153 ELSIF(v_tExprSubtype(j) = OPERATOR_DOESNOTCONTAIN)THEN
6154
6155 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ''%'' || ' ||
6156 EXAMINE_WHERE_CLAUSE(jChild + 1) || ' || ''%'')';
6157
6158 ELSIF(v_tExprSubtype(j) = OPERATOR_NOTLIKE)THEN
6159
6160 RETURN '(' || EXAMINE_WHERE_CLAUSE(jChild) || ' NOT LIKE ' ||
6161 EXAMINE_WHERE_CLAUSE(jChild + 1) || ')';
6162
6163 ELSE
6164
6165 RAISE CZ_E_UKNOWN_OPER_IN_COMPAT;
6166 END IF;
6167
6168 ELSIF(v_tExprSubtype(j) = OPERATOR_NOT)THEN
6169
6170 RETURN '(NOT ' || EXAMINE_WHERE_CLAUSE(jChild) || ')';
6171
6172 ELSE
6173
6174 RAISE CZ_E_WRONG_OPER_IN_COMPAT;
6175 END IF;
6176 ELSE
6177
6178 RAISE CZ_R_WRONG_COMPAT_EXPRESSION;
6179 END IF;
6180 END;
6181 ---------------------------------------------------------------------------------------
6182 PROCEDURE GET_ITEM_INDEX(OptionId IN NUMBER, ColumnIndex IN PLS_INTEGER) IS --kdande; Bug 6881902; 11-Mar-2008
6183 BEGIN
6184
6185 IF(NOT v_OptionExists.EXISTS(OptionId))THEN
6186 v_OptionExists(OptionId) := chainIndex;
6187 ELSE
6188 currentIndex := v_OptionExists(OptionId);
6189 LOOP
6190
6191 IF(v_FeatureIndex(currentIndex) = ColumnIndex)THEN
6192 itemIndex := v_ItemIndex(currentIndex);
6193 RETURN;
6194 END IF;
6195
6196 EXIT WHEN v_OptionsChain(currentIndex) IS NULL;
6197 currentIndex := v_OptionsChain(currentIndex);
6198 END LOOP;
6199
6200 v_OptionsChain(currentIndex) := chainIndex;
6201 END IF;
6202
6203 --Bug #4546828. Use the hashed explosion id for each option.
6204
6205 v_ItemLines(itemCount) := GENERATE_NAME_EXPL(h_OptionExplId(ColumnIndex)(OptionId), OptionId) || ' ' || TO_CHAR(ColumnIndex - 1);
6206
6207 v_OptionsChain(chainIndex) := NULL;
6208 v_FeatureIndex(chainIndex) := ColumnIndex;
6209 v_ItemIndex(chainIndex) := itemCount;
6210 itemIndex := itemCount;
6211 itemCount := itemCount + 1;
6212 chainIndex := chainIndex + 1;
6213 END;
6214 ---------------------------------------------------------------------------------------
6215 PROCEDURE GENERATE_STANDARD_PBC IS
6216 BEGIN
6217 v_cursor := DBMS_SQL.OPEN_CURSOR;
6218 DBMS_SQL.PARSE(v_cursor, SQLSelect || SQLFrom || SQLWhere, DBMS_SQL.NATIVE);
6219
6220 FOR i IN 1..bindValue.COUNT LOOP
6221 DBMS_SQL.BIND_VARIABLE(v_cursor, ':x' || TO_CHAR(i), bindValue(i));
6222 END LOOP;
6223
6224 nDebug := 7005109;
6225
6226 localNumber := DBMS_SQL.EXECUTE(v_cursor);
6227
6228 LOOP
6229
6230 FOR i IN 1..iteratorIndex.COUNT LOOP
6231 DBMS_SQL.DEFINE_ARRAY(v_cursor, i, v_tOptionId, DBMS_SQL_MAX_BUFFER_SIZE, 1);
6232 END LOOP;
6233
6234 localNumber := DBMS_SQL.FETCH_ROWS(v_cursor);
6235
6236 FOR i IN 1..v_tFeatureId.COUNT LOOP
6237
6238 DBMS_SQL.COLUMN_VALUE(v_cursor, i, v_tOptionId);
6239
6240 FOR n IN 1..localNumber LOOP
6241
6242 GET_ITEM_INDEX(v_tOptionId(n), i);
6243
6244 --Fix for the bug #2256166: changed n to rowThreshold + n in the EXISTS operator.
6245
6246 IF(v_RowLines.EXISTS(rowThreshold + n))THEN
6247 v_RowLines(rowThreshold + n) := v_RowLines(rowThreshold + n) || ' ' || TO_CHAR(itemIndex - 1);
6248 ELSE
6249 v_RowLines(rowThreshold + n) := ' ' || TO_CHAR(itemIndex - 1);
6250 END IF;
6251 END LOOP;
6252 END LOOP;
6253 EXIT WHEN localNumber <> DBMS_SQL_MAX_BUFFER_SIZE;
6254 rowThreshold := rowThreshold + DBMS_SQL_MAX_BUFFER_SIZE;
6255 END LOOP;
6256
6257 nDebug := 7005110;
6258
6259 DBMS_SQL.CLOSE_CURSOR(v_cursor);
6260
6261 --If there's no valid combinations, report the rule and ignore it.
6262
6263 IF(v_RowLines.COUNT = 0)THEN
6264 RAISE CZ_R_COMPAT_NO_COMBINATIONS;
6265 END IF;
6266
6267 --Generate the combo structure
6268
6269 vLogicLine := 'OBJECT P_R' || TO_CHAR(nRuleId) || '_' || TO_CHAR(v_tExprId(j)) || NewLine ||
6270 'COMBO P_R' || TO_CHAR(nRuleId) || '_' || TO_CHAR(v_tExprId(j)) || ' ' ||
6271 TO_CHAR(v_ItemLines.COUNT) || ' ' || TO_CHAR(v_RowLines.COUNT) || ' ' ||
6272 TO_CHAR(v_tFeatureId.COUNT) || ' ... ' || TO_CHAR(nReasonId) || NewLine;
6273 PACK;
6274
6275 FOR i IN 1..v_ItemLines.COUNT LOOP
6276
6277 vLogicLine := 'CI ' || TO_CHAR(i - 1) || ' ' || v_ItemLines(i) || NewLine;
6278 PACK;
6279 END LOOP;
6280
6281 FOR i IN 1..v_tFeatureId.COUNT LOOP
6282
6283 IF(GenerateGatedCombo = 0)THEN
6284
6285 --Use intermediate variable instead of using NVL because this is faster
6286
6287 localNumber := glIndexByPsNodeId(v_tFeatureId(i));
6288 localString := TO_CHAR(glMaximum(localNumber));
6289
6290 --If it's a BOM item, we use maximum_selected instead of maximum
6291
6292 IF(glPsNodeType(localNumber) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
6293 localString := TO_CHAR(glMaximumSel(localNumber));
6294 END IF;
6295
6296 IF(localString IS NULL)THEN localString := '-1'; END IF;
6297 vLogicLine := ' O';
6298 ELSE
6299
6300 --Generate gated combinations: maximum is always -1, the 'G' argument is followed
6301 --by the feature name.
6302
6303 localString := '-1';
6304 vLogicLine := ' G ' || GENERATE_NAME(v_BackIndex(i), v_tFeatureId(i));
6305 END IF;
6306
6307 vLogicLine := 'CC ' || TO_CHAR(i - 1) || ' 0 ' || localString || vLogicLine || NewLine;
6308 PACK;
6309 END LOOP;
6310
6311 FOR i IN 1..v_RowLines.COUNT LOOP
6312
6313 vLogicLine := 'CR ' || TO_CHAR(i - 1) || v_RowLines(i) || NewLine;
6314 PACK;
6315 END LOOP;
6316
6317 vLogicLine := 'COMBO_END' || NewLine;
6318 PACK;
6319
6320 --Generate the exclude relations if necessary.
6321 --The code is re-written as part of the fix for the bug #4546828 to use the new hash table.
6322
6323 FOR i IN 1..v_tFeatureId.COUNT LOOP
6324
6325 --We will use this array in the local context now
6326
6327 v_OptionExists.DELETE;
6328
6329 FOR n IN 1..v_ItemLines.COUNT LOOP
6330
6331 itemIndex := INSTR(v_ItemLines(n), ' ', -1) + 1;
6332
6333 IF(TO_NUMBER(SUBSTR(v_ItemLines(n), itemIndex)) = i - 1)THEN
6334
6335 currentIndex := INSTR(v_ItemLines(n), '_', -1) + 1;
6336 v_OptionExists(TO_NUMBER(SUBSTR(v_ItemLines(n), currentIndex, itemIndex - currentIndex - 1))) := 1;
6337 END IF;
6338 END LOOP;
6339
6340 ExcludesRequired := 0;
6341 nChild := h_OptionExplId(i).FIRST;
6342 nCounter := nChild;
6343
6344 WHILE(nChild IS NOT NULL) LOOP
6345 IF(NOT v_OptionExists.EXISTS(glPersistentId(nChild)))THEN
6346 ExcludesRequired := 1;
6347 EXIT;
6348 END IF;
6349 nChild := h_OptionExplId(i).NEXT(nChild);
6350 END LOOP;
6351
6352 IF(ExcludesRequired = 1)THEN
6353
6354 nChild := nCounter;
6355
6356 vLogicLine := 'GS E ... ' || TO_CHAR(nReasonId) || NewLine || 'GL N ';
6357 PACK;
6358
6359 WHILE(nChild IS NOT NULL) LOOP
6360 IF(NOT v_OptionExists.EXISTS(glPersistentId(nChild)))THEN
6361 vLogicLine := GENERATE_NAME_EXPL(h_OptionExplId(i)(nChild), nChild) || ' ';
6362 PACK;
6363 END IF;
6364 nChild := h_OptionExplId(i).NEXT(nChild);
6365 END LOOP;
6366
6367 vLogicLine := NewLine || 'GR L ';
6368 PACK;
6369
6370 FOR n IN 1..v_tFeatureId.COUNT LOOP
6371 IF(n <> i)THEN
6372 vLogicLine := GENERATE_NAME(v_BackIndex(n), v_tFeatureId(n)) || ' ';
6373 PACK;
6374 END IF;
6375 END LOOP;
6376
6377 vLogicLine := NewLine;
6378 PACK;
6379 END IF; --Excludes required
6380 END LOOP;
6381 END GENERATE_STANDARD_PBC;
6382 ---------------------------------------------------------------------------------------
6383 PROCEDURE GENERATE_OPTIMIZED_PBC IS
6384
6385 TYPE tVarcharTable IS TABLE OF VARCHAR2(32000) INDEX BY VARCHAR2(32000);
6386
6387 v_options SYSTEM.cz_lce_compat_tab_type := SYSTEM.cz_lce_compat_tab_type();
6388 a_min PLS_INTEGER;
6389 b_min PLS_INTEGER;
6390 a_object_name VARCHAR2(4000);
6391 b_object_name VARCHAR2(4000);
6392 v_option_a DBMS_SQL.NUMBER_TABLE;
6393 v_option_b DBMS_SQL.NUMBER_TABLE;
6394 current_option NUMBER;
6395 v_bitpos_a tIntegerArray_idx_vc2; --jonatara:bug7041718
6396 v_bitpos_b tIntegerArray_idx_vc2;
6397 v_bitinv_a tIntegerArray;
6398 v_bitinv_b tIntegerArray;
6399 v_mask VARCHAR2(32000);
6400 v_group VARCHAR2(32000);
6401 v_rel VARCHAR2(1);
6402 v_group_by_set_mask_a tVarcharTable;
6403 v_group_by_set_mask_b tVarcharTable;
6404 /*-------------------------------------------------------------------------------------
6405 CREATE OR REPLACE TYPE cz_lce_compat_rec_type IS OBJECT (option_a NUMBER, option_b NUMBER);
6406 CREATE OR REPLACE TYPE cz_lce_compat_tab_type IS TABLE OF cz_lce_compat_rec_type;
6407 ---------------------------------------------------------------------------------------*/
6408 FUNCTION get_feature_minimum(p_feature_id IN NUMBER) RETURN PLS_INTEGER IS
6409 v_idx NUMBER; --kdande; Bug 6881902; 11-Mar-2008
6410 v_min NUMBER; --kdande; Bug 6881902; 11-Mar-2008
6411 BEGIN
6412 v_idx := glIndexByPsNodeId(p_feature_id);
6413 v_min := glMinimum(v_idx);
6414
6415 IF(glPsNodeType(v_idx) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
6416 v_min := glMinimumSel(v_idx);
6417 END IF;
6418 if(v_min IS NULL OR v_min < 1)THEN RETURN 0; END IF;
6419 RETURN 1;
6420 END;
6421 ---------------------------------------------------------------------------------------
6422 PROCEDURE init_set_mask(p_size IN PLS_INTEGER) IS
6423 BEGIN
6424 v_mask := '0';
6425 v_mask := RPAD(v_mask, p_size, '0');
6426 END;
6427 ---------------------------------------------------------------------------------------
6428 PROCEDURE set_mask(p_bitpos IN PLS_INTEGER) IS
6429 BEGIN
6430 v_mask := SUBSTR(v_mask, 1, p_bitpos - 1) || '1' || SUBSTR(v_mask, p_bitpos + 1);
6431 END;
6432 ---------------------------------------------------------------------------------------
6433 PROCEDURE init_group_mask_a(p_key IN VARCHAR2) IS
6434 BEGIN
6435 v_group_by_set_mask_a(p_key) := '0';
6436 v_group_by_set_mask_a(p_key) := RPAD(v_group_by_set_mask_a(p_key), v_bitpos_a.COUNT, '0');
6437 END;
6438 ---------------------------------------------------------------------------------------
6439 PROCEDURE set_group_mask_a(p_key IN VARCHAR2, p_bitpos IN PLS_INTEGER) IS
6440 BEGIN
6441 v_group_by_set_mask_a(p_key) := SUBSTR(v_group_by_set_mask_a(p_key), 1, p_bitpos - 1)
6442 || '1' || SUBSTR(v_group_by_set_mask_a(p_key), p_bitpos + 1);
6443 END;
6444 ---------------------------------------------------------------------------------------
6445 PROCEDURE init_group_mask_b(p_key IN VARCHAR2) IS
6446 BEGIN
6447 v_group_by_set_mask_b(p_key) := '0';
6448 v_group_by_set_mask_b(p_key) := RPAD(v_group_by_set_mask_b(p_key), v_bitpos_b.COUNT, '0');
6449 END;
6450 ---------------------------------------------------------------------------------------
6451 PROCEDURE set_group_mask_b(p_key IN VARCHAR2, p_bitpos IN PLS_INTEGER) IS
6452 BEGIN
6453 v_group_by_set_mask_b(p_key) := SUBSTR(v_group_by_set_mask_b(p_key), 1, p_bitpos - 1)
6454 || '1' || SUBSTR(v_group_by_set_mask_b(p_key), p_bitpos + 1);
6455 END;
6456 ---------------------------------------------------------------------------------------
6457 FUNCTION in_mask(p_bitpos IN PLS_INTEGER) RETURN BOOLEAN IS
6458 BEGIN
6459 RETURN (SUBSTR(v_mask, p_bitpos, 1) = '1');
6460 END;
6461 ---------------------------------------------------------------------------------------
6462 FUNCTION in_group(p_bitpos IN PLS_INTEGER) RETURN BOOLEAN IS
6463 BEGIN
6464 RETURN (SUBSTR(v_group, p_bitpos, 1) = '1');
6465 END;
6466 ---------------------------------------------------------------------------------------
6467 BEGIN
6468 nDebug := 8000000;
6469 v_cursor := DBMS_SQL.OPEN_CURSOR;
6470 DBMS_SQL.PARSE(v_cursor, SQLSelect || SQLFrom || SQLWhere, DBMS_SQL.NATIVE);
6471
6472 FOR i IN 1..bindValue.COUNT LOOP
6473 DBMS_SQL.BIND_VARIABLE(v_cursor, ':x' || TO_CHAR(i), bindValue(i));
6474 END LOOP;
6475
6476 localNumber := DBMS_SQL.EXECUTE(v_cursor);
6477 nDebug := 8000001;
6478 LOOP
6479
6480 DBMS_SQL.DEFINE_ARRAY(v_cursor, 1, v_option_a, DBMS_SQL_MAX_BUFFER_SIZE, 1);
6481 DBMS_SQL.DEFINE_ARRAY(v_cursor, 2, v_option_b, DBMS_SQL_MAX_BUFFER_SIZE, 1);
6482
6483 localNumber := DBMS_SQL.FETCH_ROWS(v_cursor);
6484
6485 DBMS_SQL.COLUMN_VALUE(v_cursor, 1, v_option_a);
6486 DBMS_SQL.COLUMN_VALUE(v_cursor, 2, v_option_b);
6487 nDebug := 8000002;
6488 FOR i IN 1..localNumber LOOP
6489 v_options.EXTEND();
6490 v_options(rowThreshold + i) := SYSTEM.cz_lce_compat_rec_type(v_option_a(i), v_option_b(i));
6491 nDebug := 8000003;
6492 --These arrays store 'bit positions' for every a or b option. Later they will be used in construction
6493 --of the 'bit masks' for compatibility groups and sets.
6494 --The 'inv' arrays allow to quickly get an option_id by its bit position.
6495
6496 IF(NOT v_bitpos_a.EXISTS(v_option_a(i)))THEN
6497
6498 v_bitpos_a(v_option_a(i)) := v_bitpos_a.COUNT + 1;
6499 v_bitinv_a(v_bitpos_a(v_option_a(i))) := v_option_a(i);
6500 END IF;
6501 IF(NOT v_bitpos_b.EXISTS(v_option_b(i)))THEN
6502
6503 v_bitpos_b(v_option_b(i)) := v_bitpos_b.COUNT + 1;
6504 v_bitinv_b(v_bitpos_b(v_option_b(i))) := v_option_b(i);
6505 END IF;
6506 END LOOP;
6507
6508 v_option_a.DELETE;
6509 v_option_b.DELETE;
6510
6511 EXIT WHEN localNumber <> DBMS_SQL_MAX_BUFFER_SIZE;
6512 rowThreshold := rowThreshold + DBMS_SQL_MAX_BUFFER_SIZE;
6513 END LOOP;
6514 nDebug := 8000005;
6515 DBMS_SQL.CLOSE_CURSOR(v_cursor);
6516
6517 --If there's no valid combinations, report the rule and ignore it.
6518
6519 IF(v_options.COUNT = 0)THEN
6520 RAISE CZ_R_COMPAT_NO_COMBINATIONS;
6521 END IF;
6522
6523 IF (v_options.COUNT = (featOptionsCount(v_tFeatureId(1)) * featOptionsCount(v_tFeatureId(2)))) THEN
6524
6525 --This is a two-column pbc rule, and the number of valid combinations is equal to the
6526 --number of possible combinations. The rule can be ignored.
6527
6528 RETURN;
6529 END IF;
6530
6531 a_min := get_feature_minimum(v_tFeatureId(1));
6532 b_min := get_feature_minimum(v_tFeatureId(2));
6533
6534 --Generate the main relations.
6535
6536 IF(a_min = 0)THEN
6537
6538 --We need a temporary object to represent Not(A).
6539
6540 nLocalDefaults := nLocalDefaults + 1;
6541 a_object_name := t_prefix || TO_CHAR(nLocalDefaults);
6542
6543 vLogicLine := 'OBJECT ' || a_object_name || NewLine ||
6544 'GS N ... ' || TO_CHAR(nReasonId) || NewLine ||
6545 'GL' || OperatorLetters(OPERATOR_ANYOF) || GENERATE_NAME(v_BackIndex(1), v_tFeatureId(1)) || NewLine ||
6546 'GR' || OperatorLetters(OPERATOR_ANYOF) || a_object_name || NewLine;
6547 PACK;
6548 a_object_name := a_object_name || ' ';
6549 END IF;
6550
6551 IF(b_min = 0)THEN
6552
6553 --We need a temporary object to represent Not(B).
6554
6555 nLocalDefaults := nLocalDefaults + 1;
6556 b_object_name := t_prefix || TO_CHAR(nLocalDefaults);
6557
6558 vLogicLine := 'OBJECT ' || b_object_name || NewLine ||
6559 'GS N ... ' || TO_CHAR(nReasonId) || NewLine ||
6560 'GL' || OperatorLetters(OPERATOR_ANYOF) || GENERATE_NAME(v_BackIndex(2), v_tFeatureId(2)) || NewLine ||
6561 'GR' || OperatorLetters(OPERATOR_ANYOF) || b_object_name || NewLine;
6562 PACK;
6563 b_object_name := b_object_name || ' ';
6564 END IF;
6565
6566 current_option := -1;
6567 nDebug := 8000010;
6568 FOR a IN (SELECT option_a, option_b FROM TABLE(v_options) ORDER BY option_a) LOOP
6569
6570 IF(a.option_a <> current_option)THEN
6571
6572 IF(current_option <> -1)THEN
6573
6574 --We just moved to the next option. current_option is still the previous option for
6575 --which the generating of the compatible set mask is completed, and the actual mask
6576 --is still in v_mask.
6577 --Here either add the options to an existing compatibility group mask, or create a
6578 --new compatibility group mask.
6579
6580 IF(NOT v_group_by_set_mask_a.EXISTS(v_mask))THEN init_group_mask_a(v_mask); END IF;
6581 set_group_mask_a(v_mask, v_bitpos_a(current_option));
6582 END IF;
6583
6584 current_option := a.option_a;
6585 init_set_mask(v_bitpos_b.COUNT);
6586 END IF;
6587
6588 set_mask(v_bitpos_b(a.option_b));
6589 END LOOP;
6590
6591 --Need to repeat that for the last option.
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
6596 current_option := -1;
6597
6598 FOR b IN (SELECT option_a, option_b FROM TABLE(v_options) ORDER BY option_b) LOOP
6599
6600 IF(b.option_b <> current_option)THEN
6601
6602 IF(current_option <> -1)THEN
6603
6604 IF(NOT v_group_by_set_mask_b.EXISTS(v_mask))THEN init_group_mask_b(v_mask); END IF;
6605 set_group_mask_b(v_mask, v_bitpos_b(current_option));
6606 END IF;
6607
6608 current_option := b.option_b;
6609 init_set_mask(v_bitpos_a.COUNT);
6610 END IF;
6611
6612 set_mask(v_bitpos_a(b.option_a));
6613 END LOOP;
6614
6615 --Need to repeat that for the last option.
6616 nDebug := 8000015;
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
6620 --The tables of compatibility group masks hashed by compatibility set masks have been built
6621 --for both sides. Now we can use them to generate the relations.
6622
6623 v_mask := v_group_by_set_mask_a.FIRST;
6624
6625 WHILE(v_mask IS NOT NULL)LOOP
6626
6627 v_group := v_group_by_set_mask_a(v_mask);
6628 v_rel := 'I';
6629
6630 IF(a_min = 1 AND b_min = 1 AND
6631 v_group_by_set_mask_b.EXISTS(v_group) AND v_group_by_set_mask_b(v_group) = v_mask)THEN
6632
6633 --This is A Implies B, B Implies A. A Requires relation will be generated between v_group and
6634 --v_mask and v_group_by_set_mask_b(v_group) will be deleted so that it will not be processed
6635 --by the cycle on the other side.
6636
6637 v_rel := 'R';
6638 v_group_by_set_mask_b.DELETE(v_group);
6639 END IF;
6640
6641 --Generate an Implies or Requires relation between AnyTrue(v_group) and AnyTrue(v_mask)
6642
6643 vLogicLine := 'GS ' || v_rel || ' ... ' || TO_CHAR(nReasonId) || NewLine || 'GL N '; PACK;
6644
6645 FOR i IN 1..v_bitpos_a.COUNT LOOP
6646 IF(in_group(i))THEN
6647 vLogicLine := GENERATE_NAME(v_BackIndex(1), v_bitinv_a(i)) || ' '; PACK;
6648 END IF;
6649 END LOOP;
6650
6651 vLogicLine := NewLine || 'GR N ' || b_object_name; PACK;
6652 nDebug := 8000020;
6653 FOR i IN 1..v_bitpos_b.COUNT LOOP
6654 IF(in_mask(i))THEN
6655 vLogicLine := GENERATE_NAME(v_BackIndex(2), v_bitinv_b(i)) || ' '; PACK;
6656 END IF;
6657 END LOOP;
6658
6659 vLogicLine := NewLine;
6660 PACK;
6661 v_mask := v_group_by_set_mask_a.NEXT(v_mask);
6662 END LOOP;
6663
6664 v_mask := v_group_by_set_mask_b.FIRST;
6665
6666 WHILE(v_mask IS NOT NULL)LOOP
6667
6668 v_group := v_group_by_set_mask_b(v_mask);
6669 v_rel := 'I';
6670
6671 IF(a_min = 1 AND b_min = 1 AND
6672 v_group_by_set_mask_a.EXISTS(v_group) AND v_group_by_set_mask_a(v_group) = v_mask)THEN
6673
6674 --This is B Implies A, A Implies B. A Requires relation will be generated between v_group and
6675 --v_mask. We don't need to delete anything from the other side.
6676
6677 v_rel := 'R';
6678 END IF;
6679
6680 --Generate an Implies or Requires relation between AnyTrue(v_group) and AnyTrue(v_mask)
6681
6682 vLogicLine := 'GS ' || v_rel || ' ... ' || TO_CHAR(nReasonId) || NewLine || 'GL N '; PACK;
6683 nDebug := 8000025;
6684 FOR i IN 1..v_bitpos_b.COUNT LOOP
6685 IF(in_group(i))THEN
6686 vLogicLine := GENERATE_NAME(v_BackIndex(2), v_bitinv_b(i)) || ' '; PACK;
6687 END IF;
6688 END LOOP;
6689
6690 vLogicLine := NewLine || 'GR N ' || a_object_name; PACK;
6691
6692 FOR i IN 1..v_bitpos_a.COUNT LOOP
6693 IF(in_mask(i))THEN
6694 vLogicLine := GENERATE_NAME(v_BackIndex(1), v_bitinv_a(i)) || ' '; PACK;
6695 END IF;
6696 END LOOP;
6697
6698 vLogicLine := NewLine;
6699 PACK;
6700 v_mask := v_group_by_set_mask_b.NEXT(v_mask);
6701 END LOOP;
6702
6703 -- The following block can be optimized by splitting into two (for a and b), and
6704 -- 1) using featOptionsCount table and compare it to v_bitpos_a(b).COUNT to find out if excludes
6705 -- are required instead of cycling through the feature options;
6706 -- 2) using v_bitpos_a(b) instead of v_OptionExists thus avoiding populating this table.
6707
6708 v_OptionExists.DELETE;
6709
6710 --Hash all the options of both features that are compatible. If an option is not in the hash,
6711 --exclude relation will be generated later.
6712 nDebug := 8000030;
6713 FOR i IN 1..v_options.COUNT LOOP
6714 v_OptionExists(v_options(i).option_a) := 1;
6715 v_OptionExists(v_options(i).option_b) := 1;
6716 END LOOP;
6717
6718 --Generate the exclude relations if necessary.
6719 --The code is re-written as part of the fix for the bug #4546828 to use the new hash table.
6720
6721 FOR i IN 1..v_tFeatureId.COUNT LOOP
6722
6723 ExcludesRequired := 0;
6724 nChild := h_OptionExplId(i).FIRST;
6725 nCounter := nChild;
6726
6727 WHILE(nChild IS NOT NULL) LOOP
6728 IF(NOT v_OptionExists.EXISTS(nChild))THEN
6729 ExcludesRequired := 1;
6730 EXIT;
6731 END IF;
6732 nChild := h_OptionExplId(i).NEXT(nChild);
6733 END LOOP;
6734
6735 IF(ExcludesRequired = 1)THEN
6736
6737 nChild := nCounter;
6738 nDebug := 8000040;
6739 vLogicLine := 'GS E ... ' || TO_CHAR(nReasonId) || NewLine || 'GL N ';
6740 PACK;
6741
6742 WHILE(nChild IS NOT NULL) LOOP
6743 IF(NOT v_OptionExists.EXISTS(nChild))THEN
6744 vLogicLine := GENERATE_NAME_EXPL(h_OptionExplId(i)(nChild), nChild) || ' ';
6745 PACK;
6746 END IF;
6747 nChild := h_OptionExplId(i).NEXT(nChild);
6748 END LOOP;
6749
6750 vLogicLine := NewLine || 'GR L ';
6751 PACK;
6752
6753 FOR n IN 1..v_tFeatureId.COUNT LOOP
6754 IF(n <> i)THEN
6755 vLogicLine := GENERATE_NAME(v_BackIndex(n), v_tFeatureId(n)) || ' ';
6756 PACK;
6757 END IF;
6758 END LOOP;
6759
6760 vLogicLine := NewLine;
6761 PACK;
6762 END IF; --Excludes required
6763 END LOOP;
6764 END GENERATE_OPTIMIZED_PBC;
6765 ---------------------------------------------------------------------------------------
6766 BEGIN
6767
6768 --High-level property-based compatibility rule validation section
6769 --Make sure the rule has at least 2 participant features
6770
6771 IF(participantCount < 2)THEN
6772 RAISE CZ_R_COMPAT_SINGLE_FEATURE;
6773 END IF;
6774
6775 nDebug := 7005100;
6776
6777 nChild := v_ChildrenIndex(v_tExprId(j));
6778 nCounter := 1;
6779
6780 WHILE(v_tExprParentId(nChild) = v_tExprId(j)) LOOP
6781 IF(v_tExprType(nChild) = EXPR_ITERATOR)THEN
6782
6783 iteratorIndex(nCounter) := nChild;
6784 featureIndex := v_ChildrenIndex(v_tExprId(nChild));
6785
6786 v_tFeatureId(nCounter) := v_tExprPsNodeId(featureIndex);
6787 v_tExplId(nCounter) := v_tExplNodeId(featureIndex);
6788 v_BackIndex(nCounter) := featureIndex;
6789
6790 nCounter := nCounter + 1;
6791
6792 ELSIF(v_tExprType(nChild) = EXPR_WHERE)THEN
6793
6794 whereIndex := nChild;
6795 END IF;
6796
6797 nChild := nChild + 1;
6798 END LOOP;
6799
6800 nDebug := 7005101;
6801
6802 FOR i IN 1..iteratorIndex.COUNT LOOP
6803
6804 bind_node_id.DELETE;
6805 bind_values.DELETE;
6806
6807 v_property_id.DELETE;
6808 v_data_type.DELETE;
6809 v_prop_name.DELETE;
6810 v_flag.DELETE;
6811
6812 temp_cmpt_hash_key(compatLevel) := NULL;
6813 tableAlias := 'C' || TO_CHAR(i);
6814
6815 iterator.DELETE;
6816 iterator := GENERATE_ITERATOR(iteratorIndex(i), ListType);
6817
6818 IF(whereIndex <> 0)THEN
6819 EXPLORE_WHERE(whereIndex, v_tExprArgumentName(iteratorIndex(i)));
6820 END IF;
6821
6822 IF(temp_cmpt_hash_key(compatLevel) IS NOT NULL)THEN
6823 FOR ii IN 1..v_property_id.COUNT LOOP
6824 temp_cmpt_hash_key(compatLevel) := temp_cmpt_hash_key(compatLevel) || '-' || TO_CHAR(v_property_id(ii));
6825 END LOOP;
6826 END IF;
6827
6828 nDebug := 7005102;
6829
6830 IF(temp_cmpt_hash_key(compatLevel) IS NOT NULL AND temp_cmpt_table_hash.EXISTS(temp_cmpt_hash_key(compatLevel)))THEN
6831
6832 tableName := temp_cmpt_table_hash(temp_cmpt_hash_key(compatLevel));
6833 arg_table_name(v_tExprArgumentName(iteratorIndex(i))) := tableAlias;
6834
6835 IF(SQLSelect IS NULL)THEN SQLSelect := 'SELECT '; ELSE SQLSelect := SQLSelect || ', '; END IF;
6836 SQLSelect := SQLSelect || tableAlias || '.node_id';
6837 IF(SQLFrom IS NULL)THEN SQLFrom := ' FROM '; ELSE SQLFrom := SQLFrom || ', '; END IF;
6838 SQLFrom := SQLFrom || tableName || ' ' || tableAlias;
6839
6840 FOR ii IN 1..iterator.COUNT LOOP
6841 h_OptionExplId(i)(iterator(ii).node_id) := iterator(ii).node_id_ex;
6842 END LOOP;
6843 ELSE
6844
6845 tableName := 'G_' || TO_CHAR(table_name_generator);
6846 table_name_generator := table_name_generator + 1;
6847 arg_table_name(v_tExprArgumentName(iteratorIndex(i))) := tableAlias;
6848
6849 IF(SQLSelect IS NULL)THEN SQLSelect := 'SELECT '; ELSE SQLSelect := SQLSelect || ', '; END IF;
6850 SQLSelect := SQLSelect || tableAlias || '.node_id';
6851 IF(SQLFrom IS NULL)THEN SQLFrom := ' FROM '; ELSE SQLFrom := SQLFrom || ', '; END IF;
6852 SQLFrom := SQLFrom || tableName || ' ' || tableAlias;
6853
6854 SQLCreate := 'CREATE GLOBAL TEMPORARY TABLE ' || tableName || '(node_id NUMBER ';
6855
6856 FOR ii IN 1..v_property_id.COUNT LOOP
6857
6858 SQLCreate := SQLCreate || ', i_' || TO_CHAR(v_property_id(ii));
6859
6860 IF(v_data_type(ii) IN (DATA_TYPE_INTEGER, DATA_TYPE_DECIMAL))THEN
6861
6862 SQLCreate := SQLCreate || ' NUMBER';
6863 ELSE
6864
6865 SQLCreate := SQLCreate || ' VARCHAR2(' || TO_CHAR(MAXIMUM_INDEX_LENGTH) || ')';
6866 END IF;
6867 END LOOP;
6868
6869 SQLCreate := SQLCreate || ') ON COMMIT PRESERVE ROWS';
6870
6871 nDebug := 7005103;
6872
6873 BEGIN
6874 EXECUTE IMMEDIATE SQLCreate;
6875 EXCEPTION
6876 WHEN OTHERS THEN
6877
6878 --If the table already exists, truncate it, drop and try to create again.
6879
6880 IF(SQLCODE = ORACLE_OBJECT_ALREADY_EXISTS)THEN
6881 EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || tableName;
6882 EXECUTE IMMEDIATE 'DROP TABLE ' || tableName;
6883 EXECUTE IMMEDIATE SQLCreate;
6884 ELSE
6885 RAISE;
6886 END IF;
6887 END;
6888
6889 --The table is created, add its name to the delete list.
6890
6891 temp_tables(temp_tables.COUNT + 1) := tableName;
6892
6893 nDebug := 7005104;
6894
6895 SQLInsert := 'INSERT INTO ' || tableName || '(node_id';
6896 SQLValues := ' VALUES (:y1';
6897
6898 FOR ii IN 1..v_property_id.COUNT LOOP
6899
6900 BEGIN
6901
6902 EXECUTE IMMEDIATE 'CREATE INDEX ' || tableName || '_I' || TO_CHAR(ii) || ' ON ' || tableName ||
6903 '(i_' || v_property_id(ii) || ')';
6904 EXCEPTION
6905 WHEN OTHERS THEN
6906 IF(SQLCODE <> ORACLE_OBJECT_ALREADY_EXISTS)THEN RAISE; END IF;
6907 END;
6908
6909 SQLInsert := SQLInsert || ', i_' || TO_CHAR(v_property_id(ii));
6910 SQLValues := SQLValues || ', :x' || TO_CHAR(ii);
6911 END LOOP;
6912
6913 SQLInsert := SQLInsert || ')';
6914 SQLValues := SQLValues || ')';
6915
6916 nDebug := 7005105;
6917
6918 FOR ii IN 1..iterator.COUNT LOOP
6919
6920 bind_node_id(ii) := iterator(ii).node_id;
6921
6922 IF(v_property_id.COUNT > 0)THEN
6923
6924 --This is only valid if there are properties.
6925
6926 IF(iterator(ii).node_id IS NULL)THEN RAISE CZ_R_TYPE_NO_PROPERTY; END IF;
6927
6928 nodeId := glPsNodeId(glIndexByPsNodeId(iterator(ii).node_id));
6929 itemId := glItemId(glIndexByPsNodeId(iterator(ii).node_id));
6930 END IF;
6931
6932 --Get the property values and insert the data.
6933
6934 nDebug := 7005106;
6935
6936 FOR jj IN 1..v_property_id.COUNT LOOP
6937
6938 propertyId := v_property_id(jj);
6939 hash_propval_key := TO_CHAR(nodeId) || '-' || TO_CHAR(itemId) || '-' ||
6940 TO_CHAR(propertyId) || '-' || TO_CHAR(v_flag(propertyId));
6941
6942 IF(NOT table_hash_propval.EXISTS(hash_propval_key))THEN
6943
6944 IF(v_flag(propertyId) = 0)THEN
6945
6946 --User property.
6947
6948 propertyVal := NULL;
6949 localNumber := NULL;
6950 propertyVal := GET_PROPERTY_VALUE(nodeId, propertyId, itemId, localNumber);
6951 ELSE
6952
6953 --System property.
6954
6955 localNumber := 1;
6956 propertyVal := STATIC_SYSPROP_VALUE(nodeId, propertyId, v_flag(v_property_id(jj)));
6957 END IF;
6958
6959 --Bug #3829438. Second and third columns of the cursor are not null, so localNumber can be NULL
6960 --only if no rows are fetched.
6961
6962 IF(localNumber IS NOT NULL)THEN
6963 IF(v_data_type(jj) IN (DATATYPE_INTEGER, DATATYPE_FLOAT))THEN
6964
6965 --If the property has numeric type, but the data is corrupted and the value
6966 --cannot be actually converted to a number, the generated SQL statement may
6967 --produce incomprehensive syntax errors, like 'too many columns'. To avoid
6968 --this verify the value.
6969
6970 BEGIN
6971 typeCheck := TO_NUMBER(propertyVal);
6972 EXCEPTION
6973 WHEN OTHERS THEN
6974 errorMessage := v_prop_name(jj);
6975 localString := propertyVal;
6976 RAISE CZ_R_INCORRECT_DATA_TYPE;
6977 END;
6978 ELSIF(LENGTH(propertyVal) > MAXIMUM_INDEX_LENGTH)THEN
6979
6980 errorMessage := v_prop_name(jj);
6981 nParam := glIndexByPsNodeId(v_tFeatureId(i));
6982 auxIndex := glIndexByPsNodeId(iterator(ii).node_id);
6983 RAISE CZ_R_LONG_PROPERTY_VALUE;
6984 END IF;
6985 ELSE
6986 errorMessage := v_prop_name(jj);
6987 nParam := glIndexByPsNodeId(v_tFeatureId(i));
6988 auxIndex := glIndexByPsNodeId(iterator(ii).node_id);
6989 RAISE CZ_R_OPTION_NO_PROPERTY;
6990 END IF;
6991
6992 bind_values(jj)(ii) := propertyVal;
6993 table_hash_propval(hash_propval_key) := propertyVal;
6994 ELSE
6995 bind_values(jj)(ii) := table_hash_propval(hash_propval_key);
6996 END IF;
6997 END LOOP;
6998
6999 --Bug #4546828.
7000 --In a BOM model, options can really be references to other BOM models, therefore each option
7001 --can have its own explosion id, which should be used to generate correct logic name.
7002 --Hash the explosion id(s) here in a two-dimensional table (iterator, option_id).
7003 --Here we are supposed to hash all eligible options of the parent (the eligibility determined
7004 --by EXPAND_NODE inside the GENERATE_ITERATOR). For example, if a BOM model has BOM standard
7005 --items and a non-BOM feature, only the bom items are eligible. Therefore, this table will be
7006 --used later when generating exclusions.
7007
7008 h_OptionExplId(i)(nodeId) := iterator(ii).node_id_ex;
7009 END LOOP;
7010
7011 nDebug := 7005107;
7012
7013 v_cursor := DBMS_SQL.OPEN_CURSOR;
7014 DBMS_SQL.PARSE(v_cursor, SQLInsert || SQLValues, DBMS_SQL.NATIVE);
7015
7016 DBMS_SQL.BIND_ARRAY(v_cursor, ':y1', bind_node_id);
7017
7018 FOR ii IN 1..v_property_id.COUNT LOOP
7019 DBMS_SQL.BIND_ARRAY(v_cursor, ':x' || TO_CHAR(ii), bind_values(ii));
7020 END LOOP;
7021
7022 localNumber := DBMS_SQL.EXECUTE(v_cursor);
7023 DBMS_SQL.CLOSE_CURSOR(v_cursor);
7024
7025 EXECUTE IMMEDIATE 'ANALYZE TABLE ' || tableName || ' COMPUTE STATISTICS';
7026
7027 --The table is created and populated, add its name to the hash for re-use if it is eligible.
7028
7029 IF(temp_cmpt_hash_key(compatLevel) IS NOT NULL)THEN temp_cmpt_table_hash(temp_cmpt_hash_key(compatLevel)) := tableName; END IF;
7030 END IF;
7031 END LOOP;
7032
7033 --Generate the WHERE clause and run the query with bind variables. For every row returned,
7034 --generate the expression and return the object.
7035 --To do this, add GENERATE_ARGUMENT to the GENERATE_EXPRESSION.
7036
7037 nDebug := 7005108;
7038
7039 IF(whereIndex <> 0)THEN
7040 SQLWhere := ' WHERE ' || EXAMINE_WHERE_CLAUSE(v_ChildrenIndex(v_tExprId(whereIndex)));
7041 END IF;
7042
7043 IF(v_tFeatureId.COUNT = 2)THEN
7044 GENERATE_OPTIMIZED_PBC;
7045 ELSE
7046
7047 GENERATE_STANDARD_PBC;
7048 END IF;
7049
7050 RETURN v_return;
7051 END;
7052 ---------------------------------------------------------------------------------------
7053 --This function is introduced to support the level of embedding.
7054
7055 FUNCTION GENERATE_COMPATIBLE(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
7056 v_return tStringArray;
7057 BEGIN
7058 compatLevel := compatLevel + 1;
7059 v_return := GENERATE_COMPATIBLE_(j, ListType);
7060 compatLevel := compatLevel - 1;
7061 RETURN v_return;
7062 EXCEPTION
7063 WHEN OTHERS THEN
7064 compatLevel := compatLevel - 1;
7065 RAISE;
7066 END;
7067 ---------------------------------------------------------------------------------------
7068 FUNCTION GENERATE_EXPRESSION(j IN PLS_INTEGER, ListType OUT NOCOPY PLS_INTEGER) RETURN tStringArray IS
7069 v_return tStringArray;
7070 v_result tIteratorArray;
7071 BEGIN
7072
7073 ListType := DATATYPE_GENERIC;
7074
7075 IF(v_tExprType(j) = EXPR_NODE_TYPE_NODE)THEN
7076
7077 IF(v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
7078
7079 RETURN GENERATE_REFNODE(j, ListType);
7080 ELSE
7081
7082 RETURN GENERATE_NODE(j);
7083 END IF;
7084
7085 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_FEATPROP)THEN
7086
7087 RETURN GENERATE_PROPERTY(j);
7088
7089 ELSIF(v_tExprType(j) = EXPR_PROP)THEN
7090
7091 v_return(1) := PROPERTY_VALUE(j, glIndexByPsNodeId(v_tExprPsNodeId(j - 1)), ListType);
7092
7093 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_OPERATOR)THEN
7094
7095 IF(v_tExprSubtype(j) IN (OPERATOR_ADD,
7096 OPERATOR_SUB,
7097 OPERATOR_MULT,
7098 OPERATOR_DIV,
7099 OPERATOR_ADD_INT,
7100 OPERATOR_SUB_INT,
7101 OPERATOR_MULT_INT))THEN
7102 RETURN GENERATE_ARITHMETIC(j);
7103
7104 ELSIF(v_tExprSubtype(j) IN (OPERATOR_COS,
7105 OPERATOR_ACOS,
7106 OPERATOR_COSH,
7107 OPERATOR_SIN,
7108 OPERATOR_ASIN,
7109 OPERATOR_SINH,
7110 OPERATOR_TAN,
7111 OPERATOR_ATAN,
7112 OPERATOR_TANH,
7113 OPERATOR_LOG,
7114 OPERATOR_LOG10,
7115 OPERATOR_EXP,
7116 OPERATOR_ABS,
7117 OPERATOR_SQRT))THEN
7118 RETURN GENERATE_MATH_UNARY(j);
7119
7120 ELSIF(v_tExprSubtype(j) IN (OPERATOR_MATHDIV,
7121 OPERATOR_POW,
7122 OPERATOR_POW_INT,
7123 OPERATOR_ATAN2,
7124 OPERATOR_MOD))THEN
7125 RETURN GENERATE_MATH_BINARY(j);
7126
7127 ELSIF(v_tExprSubtype(j) IN (OPERATOR_ROUNDTONEAREST,
7128 OPERATOR_ROUNDUPTONEAREST,
7129 OPERATOR_ROUNDDOWNTONEAREST))THEN
7130 RETURN GENERATE_MATH_ROUND(j);
7131
7132 ELSIF(v_tExprSubtype(j) IN (OPERATOR_CEILING,
7133 OPERATOR_FLOOR,
7134 OPERATOR_ROUND,
7135 OPERATOR_TRUNCATE))THEN
7136 RETURN GENERATE_ROUND(j);
7137
7138 ELSIF(v_tExprSubtype(j) IN (OPERATOR_AND,
7139 OPERATOR_OR))THEN
7140 RETURN GENERATE_ANDOR(j, ListType);
7141
7142 ELSIF(v_tExprSubtype(j) IN (OPERATOR_ANYOF,
7143 OPERATOR_ALLOF))THEN
7144 RETURN GENERATE_ANYALLOF(j, ListType);
7145
7146 ELSIF(v_tExprSubtype(j) = OPERATOR_NOT)THEN
7147 RETURN GENERATE_NOT(j);
7148
7149 ELSIF(v_tExprSubtype(j) = OPERATOR_NOTTRUE)THEN
7150 RETURN GENERATE_NOTTRUE(j);
7151
7152 ELSIF(v_tExprSubtype(j) IN (OPERATOR_EQUALS,
7153 OPERATOR_NOTEQUALS,
7154 OPERATOR_GT,
7155 OPERATOR_LT,
7156 OPERATOR_GE,
7157 OPERATOR_LE,
7158 OPERATOR_EQUALS_INT,
7159 OPERATOR_NOTEQUALS_INT,
7160 OPERATOR_GT_INT,
7161 OPERATOR_LT_INT,
7162 OPERATOR_GE_INT,
7163 OPERATOR_LE_INT,
7164 OPERATOR_BEGINSWITH,
7165 OPERATOR_ENDSWITH,
7166 OPERATOR_CONTAINS,
7167 OPERATOR_LIKE,
7168 OPERATOR_MATCHES,
7169 OPERATOR_DOESNOTBEGINWITH,
7170 OPERATOR_DOESNOTENDWITH,
7171 OPERATOR_DOESNOTCONTAIN,
7172 OPERATOR_NOTLIKE))THEN
7173 RETURN GENERATE_COMPARE(j);
7174
7175 ELSIF(v_tExprSubtype(j) = OPERATOR_CONCAT)THEN
7176 RETURN GENERATE_CONCAT(j, ListType);
7177
7178 ELSIF(v_tExprSubtype(j) = OPERATOR_TOTEXT)THEN
7179
7180 --Bug 5620750 - recognize and handle the new ToText operator when used outside of PBC
7181 --context.
7182
7183 RETURN GENERATE_TOTEXT(j, ListType);
7184
7185 ELSIF(v_tExprSubtype(j) = OPERATOR_OPTIONSOF)THEN
7186 RETURN GENERATE_OF(j);
7187
7188 ELSIF(v_tExprSubtype(j) IN (OPERATOR_MIN,
7189 OPERATOR_MAX))THEN
7190 RETURN GENERATE_MINMAX(j);
7191
7192 ELSIF(v_tExprSubtype(j) IN (OPERATOR_VAL))THEN
7193 RETURN GENERATE_VAL(j);
7194
7195 ELSIF(v_tExprSubtype(j) IN (RULE_OPERATOR_REQUIRES,
7196 RULE_OPERATOR_IMPLIES,
7197 RULE_OPERATOR_EXCLUDES,
7198 RULE_OPERATOR_NEGATES,
7199 RULE_OPERATOR_DEFAULTS))THEN
7200 RETURN GENERATE_LOGIC_TREE(j);
7201
7202 ELSIF(v_tExprSubtype(j) IN (RULE_OPERATOR_CONTRIBUTES,
7203 RULE_OPERATOR_CONSUMES))THEN
7204 RETURN GENERATE_NUMERIC_TREE(j);
7205
7206 ELSE
7207
7208 --This is not a built-in operator (primitive template), so generate it as a template application.
7209 --Right now there is no reason to report it as unknown.
7210
7211 RETURN GENERATE_TEMPLATE_APPLICATION (j, ListType);
7212
7213 --nParam := v_tExprSubtype(j);
7214 --RAISE CZ_E_UNKNOWN_OPERATOR_TYPE;
7215 END IF;
7216
7217 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_LITERAL)THEN
7218
7219 RETURN GENERATE_LITERAL(j);
7220
7221 ELSIF(v_tExprType(j) = EXPR_NODE_TYPE_CONSTANT)THEN
7222
7223 RETURN GENERATE_CONSTANT(j);
7224
7225 ELSIF(v_tExprType(j) IN (EXPR_FORALL, EXPR_FORALL_DISTINCT))THEN
7226
7227 v_result := GENERATE_FORALL(j, ListType);
7228
7229 FOR i IN 1..v_result.COUNT LOOP
7230 v_return(i) := v_result(i).node_obj;
7231 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
7232 v_return(i) := GENERATE_NAME_EXPL(v_result(i).node_id_ex, v_result(i).node_id);
7233 END IF;
7234 END LOOP;
7235
7236 ELSIF(v_tExprType(j) = EXPR_COMPATIBLE)THEN
7237
7238 RETURN GENERATE_COMPATIBLE(j, ListType);
7239
7240 ELSIF(v_tExprType(j) = EXPR_ARGUMENT)THEN
7241
7242 IF(v_ChildrenIndex.EXISTS(v_tExprId(j)))THEN
7243
7244 RETURN GENERATE_REFNODE(j, ListType);
7245 ELSE
7246
7247 ListType := DATA_TYPE_VOID;
7248 RETURN GENERATE_ARGUMENT(j, ListType);
7249 END IF;
7250
7251 ELSE
7252
7253 RAISE CZ_E_UNKNOWN_EXPR_TYPE;
7254 END IF;
7255 RETURN v_return;
7256 END;
7257 ---------------------------------------------------------------------------------------
7258 PROCEDURE GENERATE_COMPATIBILITY_TABLE IS
7259 v_tOptionId tOptionId;
7260 v_OptionExists tIntegerArray_idx_vc2; --kdande; Bug 6881902; 11-Mar-2008
7261 v_RowLines tStringArray;
7262 v_ItemLines tStringArray;
7263 itemIndex PLS_INTEGER;
7264 itemCount PLS_INTEGER := 1;
7265 nChild PLS_INTEGER;
7266 nCounter PLS_INTEGER;
7267 ExcludesRequired PLS_INTEGER;
7268 PrimaryCount PLS_INTEGER;
7269 localString VARCHAR2(25);
7270 localNumber PLS_INTEGER;
7271 BEGIN
7272
7273 nDebug := 5000001;
7274
7275 FOR i IN 1..v_tExprPsNodeId.COUNT LOOP
7276
7277 v_tOptionId.DELETE;
7278 v_OptionExists.DELETE;
7279
7280 nDebug := 5000002;
7281
7282 SELECT secondary_opt_id BULK COLLECT INTO v_tOptionId
7283 FROM cz_des_chart_cells
7284 WHERE deleted_flag = FLAG_NOT_DELETED
7285 AND rule_id = nRuleId
7286 AND secondary_feature_id = v_tExprPsNodeId(i)
7287 AND secondary_feat_expl_id = v_tExplNodeId(i);
7288
7289 IF(v_tOptionId.COUNT = 0)THEN
7290 RAISE CZ_R_EMPTY_COMPAT_RULE;
7291 ELSIF(i = 1)THEN
7292 PrimaryCount := v_tOptionId.COUNT;
7293 ELSE
7294 IF(v_tOptionId.COUNT <> PrimaryCount)THEN
7295 RAISE CZ_R_WRONG_COMPAT_TABLE;
7296 END IF;
7297 END IF;
7298
7299 nDebug := 5000003;
7300
7301 FOR n IN 1..v_tOptionId.COUNT LOOP
7302
7303 --Make sure the option exists
7304
7305 IF(NOT glIndexByPsNodeId.EXISTS(v_tOptionId(n)))THEN
7306 RAISE CZ_R_INCORRECT_NODE_ID;
7307 END IF;
7308
7309 IF(NOT v_OptionExists.EXISTS(v_tOptionId(n)))THEN
7310
7311 nDebug := 5000004;
7312
7313 v_ItemLines(itemCount) := GENERATE_NAME(i, v_tOptionId(n)) || ' ' || TO_CHAR(i - 1);
7314 v_OptionExists(v_tOptionId(n)) := itemCount;
7315 itemCount := itemCount + 1;
7316
7317 END IF;
7318
7319 nDebug := 5000005;
7320
7321 itemIndex := v_OptionExists(v_tOptionId(n));
7322
7323 IF(v_RowLines.EXISTS(n))THEN
7324 v_RowLines(n) := v_RowLines(n) || ' ' || TO_CHAR(itemIndex - 1);
7325 ELSE
7326 v_RowLines(n) := ' ' || TO_CHAR(itemIndex - 1);
7327 END IF;
7328
7329 END LOOP;
7330
7331 nDebug := 5000006;
7332
7333 nChild := glIndexByPsNodeId(v_tExprPsNodeId(i)) + 1;
7334 nCounter := nChild;
7335 ExcludesRequired := 0;
7336
7337 nDebug := 5000007;
7338
7339 WHILE(glParentId.EXISTS(nChild) AND glParentId(nChild) = v_tExprPsNodeId(i))LOOP
7340 IF(NOT v_OptionExists.EXISTS(glPsNodeId(nChild)))THEN
7341 ExcludesRequired := 1;
7342 EXIT;
7343 END IF;
7344 nChild := nChild + 1;
7345 END LOOP;
7346
7347 nDebug := 5000008;
7348
7349 IF(ExcludesRequired = 1)THEN
7350
7351 nChild := nCounter;
7352
7353 vLogicLine := 'GS E ... ' || TO_CHAR(nReasonId) || NewLine || 'GL N ';
7354 PACK;
7355
7356 WHILE(glParentId.EXISTS(nChild) AND glParentId(nChild) = v_tExprPsNodeId(i))LOOP
7357 IF(NOT v_OptionExists.EXISTS(glPsNodeId(nChild)))THEN
7358 vLogicLine := GENERATE_NAME(i, glPsNodeId(nChild)) || ' ';
7359 PACK;
7360 END IF;
7361 nChild := nChild + 1;
7362 END LOOP;
7363
7364 nDebug := 5000009;
7365
7366 vLogicLine := NewLine || 'GR L ';
7367 PACK;
7368
7369 FOR n IN 1..v_tExprPsNodeId.COUNT LOOP
7370 IF(n <> i)THEN
7371 vLogicLine := GENERATE_NAME(n, v_tExprPsNodeId(n)) || ' ';
7372 PACK;
7373 END IF;
7374 END LOOP;
7375
7376 nDebug := 5000010;
7377
7378 vLogicLine := NewLine;
7379 PACK;
7380 END IF; --Excludes required
7381 END LOOP;
7382
7383 nDebug := 5000011;
7384
7385 vLogicLine := 'OBJECT P_R' || TO_CHAR(nRuleId) || NewLine ||
7386 'COMBO P_R' || TO_CHAR(nRuleId) || ' ' || TO_CHAR(v_ItemLines.COUNT) || ' ' ||
7387 TO_CHAR(v_RowLines.COUNT) || ' ' || TO_CHAR(v_tExprPsNodeId.COUNT) || ' ... ' ||
7388 TO_CHAR(nReasonId) || NewLine;
7389 PACK;
7390
7391 nDebug := 5000012;
7392
7393 FOR i IN 1..v_ItemLines.COUNT LOOP
7394
7395 vLogicLine := 'CI ' || TO_CHAR(i - 1) || ' ' || v_ItemLines(i) || NewLine;
7396 PACK;
7397
7398 END LOOP;
7399
7400 nDebug := 5000013;
7401
7402 FOR i IN 1..v_tExprPsNodeId.COUNT LOOP
7403
7404 IF(GenerateGatedCombo = 0)THEN
7405
7406 --Use intermediate variable instead of using NVL because this is faster
7407
7408 localNumber := glIndexByPsNodeId(v_tExprPsNodeId(i));
7409 localString := TO_CHAR(glMaximum(localNumber));
7410
7411 --If it's a BOM item, we use maximum_selected instead of maximum
7412
7413 IF(glPsNodeType(localNumber) IN (PS_NODE_TYPE_BOM_MODEL,PS_NODE_TYPE_BOM_OPTIONCLASS,PS_NODE_TYPE_BOM_STANDARD))THEN
7414 localString := TO_CHAR(glMaximumSel(localNumber));
7415 END IF;
7416
7417 IF(localString IS NULL)THEN localString := '-1'; END IF;
7418 vLogicLine := ' O';
7419 ELSE
7420
7421 --Generate gated combinations: maximum is always -1, the 'G' argument is followed
7422 --by the feature name.
7423
7424 localString := '-1';
7425 vLogicLine := ' G ' || GENERATE_NAME(i, v_tExprPsNodeId(i));
7426 END IF;
7427
7428 vLogicLine := 'CC ' || TO_CHAR(i - 1) || ' 0 ' || localString || vLogicLine || NewLine;
7429 PACK;
7430
7431 END LOOP;
7432
7433 nDebug := 5000014;
7434
7435 FOR i IN 1..v_RowLines.COUNT LOOP
7436
7437 vLogicLine := 'CR ' || TO_CHAR(i - 1) || v_RowLines(i) || NewLine;
7438 PACK;
7439
7440 END LOOP;
7441
7442 nDebug := 5000015;
7443
7444 vLogicLine := 'COMBO_END' || NewLine;
7445 PACK;
7446
7447 END;
7448 ---------------------------------------------------------------------------------------
7449 PROCEDURE GENERATE_DESIGNCHART_RULE IS
7450 vGridColumns tPsNodeId;
7451 vBackIndex tIntegerArray;
7452 nIndex PLS_INTEGER;
7453 ---------------------------------------------------------------------------------------
7454 PROCEDURE GENERATE_COMPAT_TEMPLATE(inSuffix IN PLS_INTEGER) IS
7455 v_tOptionId tOptionId;
7456 v_tPrimaryOptId tOptionId;
7457 v_tPrimaryId tOptionId;
7458 v_OptionExists tIntegerArray_idx_vc2; --kdande; Bug 6881902; 11-Mar-2008
7459 v_OptionsUsed tIntegerArray;
7460 v_StartOptionsUsed tIntegerArray;
7461 v_EndOptionsUsed tIntegerArray;
7462 v_ExcludesRequired tIntegerArray;
7463 v_RowLinesIndex tIntegerArray;
7464 v_RowLines tStringArray;
7465 v_tailRowLines tStringArray;
7466 v_ItemLines tStringArray;
7467 itemIndex PLS_INTEGER;
7468 itemCount PLS_INTEGER := 1;
7469 startCount PLS_INTEGER;
7470 nChild PLS_INTEGER;
7471 localString VARCHAR2(25);
7472 localNumber PLS_INTEGER;
7473 ---------------------------------------------------------------------------------------
7474 FUNCTION OPTION_EXISTS(nIndex IN PLS_INTEGER) RETURN PLS_INTEGER IS
7475 BEGIN
7476 FOR j IN v_StartOptionsUsed(nIndex)..v_EndOptionsUsed(nIndex) LOOP
7477 IF(v_OptionsUsed(j) = glPsNodeId(nChild))THEN RETURN 1; END IF;
7478 END LOOP;
7479 RETURN 0;
7480 END;
7481 ---------------------------------------------------------------------------------------
7482 --This procedure implements a version of QuickSort algorythm which sorts not the array
7483 --itself, but the array of pointers instead
7484
7485 PROCEDURE SORT_ARRAY_INDEX(indexStart IN PLS_INTEGER, indexEnd IN PLS_INTEGER) IS
7486 localStart PLS_INTEGER;
7487 localEnd PLS_INTEGER;
7488 localSwap PLS_INTEGER;
7489 RowLine VARCHAR2(4000);
7490 BEGIN
7491
7492 IF(indexStart >= indexEnd)THEN RETURN; END IF;
7493
7494 localStart := indexStart;
7495 localEnd := indexEnd;
7496 RowLine := v_tailRowLines(v_RowLinesIndex((localStart + localEnd) / 2));
7497
7498 WHILE(localStart < localEnd)LOOP
7499
7500 WHILE(localStart < localEnd AND v_tailRowLines(v_RowLinesIndex(localStart)) < RowLine) LOOP
7501 localStart := localStart + 1;
7502 END LOOP;
7503
7504 WHILE(localStart < localEnd AND v_tailRowLines(v_RowLinesIndex(localEnd)) > RowLine) LOOP
7505 localEnd := localEnd - 1;
7506 END LOOP;
7507
7508 IF(localStart < localEnd)THEN
7509 localSwap := v_RowLinesIndex(localStart);
7510 v_RowLinesIndex(localStart) := v_RowLinesIndex(localEnd);
7511 v_RowLinesIndex(localEnd) := localSwap;
7512 END IF;
7513
7514 localStart := localStart + 1;
7515 localEnd := localEnd - 1;
7516
7517 END LOOP;
7518
7519 IF(localEnd < localStart)THEN
7520 localSwap := localEnd;
7521 localEnd := localStart;
7522 localStart := localSwap;
7523 END IF;
7524
7525 SORT_ARRAY_INDEX(indexStart, localStart);
7526 IF(localStart = indexStart)THEN localStart := localStart + 1; END IF;
7527 SORT_ARRAY_INDEX(localStart, indexEnd);
7528 END;
7529 ---------------------------------------------------------------------------------------
7530 BEGIN
7531
7532 nDebug := 5000200;
7533
7534 FOR i IN 1..vGridColumns.COUNT LOOP --Validation and initial data for features
7535
7536 nDebug := 5000201;
7537
7538 IF(i = 1)THEN
7539
7540 --Read the list of participating options of the primary feature. Make a copy of the list
7541 --for the rule verification purposes (bug #2257421).
7542
7543 SELECT primary_opt_id, primary_opt_id BULK COLLECT INTO v_tOptionId, v_tPrimaryOptId
7544 FROM cz_des_chart_cells
7545 WHERE rule_id = nRuleId
7546 AND secondary_feature_id = vGridColumns(2)
7547 AND secondary_feat_expl_id = v_tExplNodeId(vBackIndex(2))
7548 AND deleted_flag = FLAG_NOT_DELETED
7549 ORDER BY 1, 2;
7550
7551 IF(v_tOptionId.COUNT = 0)THEN
7552
7553 --The previous query returned no rows. That means that there're no selections made for
7554 --any of the primary feature options. It's OK if we are processing an optional table,
7555 --but for the defining table we raise an exception.
7556
7557 IF(inSuffix = 0)THEN --we are processing the defining table
7558 RAISE CZ_R_NO_DEFINING_SELECTION;
7559 END IF;
7560
7561 --This is an optional table with no selections - don't generate the COMBO, just generate
7562 --an EXCLUDE relation and exit the procedure.
7563
7564 vLogicLine := 'GS E ... ' || TO_CHAR(nReasonId) || NewLine ||
7565 'GL N ' || GENERATE_NAME(vBackIndex(1), vGridColumns(1)) || NewLine ||
7566 'GR L ' || GENERATE_NAME(vBackIndex(2), vGridColumns(2)) || NewLine;
7567 PACK;
7568 RETURN;
7569
7570 END IF;
7571
7572 ELSE
7573
7574 nDebug := 5000202;
7575
7576 v_tOptionId.DELETE;
7577 v_tPrimaryId.DELETE;
7578 v_OptionExists.DELETE;
7579
7580 --Read the list of participating options of defining or optional feature.
7581
7582 SELECT secondary_opt_id, primary_opt_id BULK COLLECT INTO v_tOptionId, v_tPrimaryId
7583 FROM cz_des_chart_cells
7584 WHERE rule_id = nRuleId
7585 AND secondary_feature_id = vGridColumns(i)
7586 AND secondary_feat_expl_id = v_tExplNodeId(vBackIndex(i))
7587 AND deleted_flag = FLAG_NOT_DELETED
7588 ORDER BY primary_opt_id;
7589
7590 FOR n IN 1..v_tOptionId.COUNT LOOP
7591
7592 IF(NOT glIndexByPsNodeId.EXISTS(v_tPrimaryId(n)))THEN
7593
7594 BEGIN
7595 SELECT name INTO errorMessage FROM cz_ps_nodes
7596 WHERE ps_node_id = v_tPrimaryId(n);
7597 EXCEPTION
7598 WHEN OTHERS THEN
7599 errorMessage := 'Unknown';
7600 END;
7601
7602 RAISE CZ_R_DELETED_OPTION;
7603 END IF;
7604
7605 --Bug #2257421. The list of corresponding primary options which participate in the rule should be
7606 --equal for all defining features.
7607 --v_tPrimaryOptId - the ordered list of primary options checked for the first defining feature.
7608 --v_tPrimaryId - the ordered list of primary options checked for the current feature.
7609
7610 IF((NOT v_tPrimaryOptId.EXISTS(n)) OR (v_tPrimaryOptId(n) > v_tPrimaryId(n)))THEN
7611
7612 --Too many selections made.
7613
7614 auxCount := glIndexByPsNodeId(vGridColumns(1));
7615 auxIndex := glIndexByPsNodeId(v_tPrimaryId(n));
7616 RAISE CZ_R_INCOMPLETE_DES_CHART;
7617
7618 ELSIF(v_tPrimaryOptId(n) < v_tPrimaryId(n))THEN
7619
7620 --Too few selections made.
7621
7622 auxCount := glIndexByPsNodeId(vGridColumns(1));
7623 auxIndex := glIndexByPsNodeId(v_tPrimaryOptId(n));
7624 RAISE CZ_R_INCOMPLETE_DES_CHART;
7625 END IF;
7626 END LOOP;
7627
7628 IF(v_tPrimaryOptId.EXISTS(v_tOptionId.COUNT + 1))THEN
7629
7630 --Too few selections made.
7631
7632 auxCount := glIndexByPsNodeId(vGridColumns(1));
7633 auxIndex := glIndexByPsNodeId(v_tPrimaryOptId(v_tOptionId.COUNT + 1));
7634 RAISE CZ_R_INCOMPLETE_DES_CHART;
7635 END IF;
7636 END IF;
7637
7638 startCount := itemCount;
7639
7640 FOR n IN 1..v_tOptionId.COUNT LOOP
7641
7642 --Make sure the option exists.
7643
7644 IF(NOT glIndexByPsNodeId.EXISTS(v_tOptionId(n)))THEN
7645
7646 BEGIN
7647 SELECT name INTO errorMessage FROM cz_ps_nodes
7648 WHERE ps_node_id = v_tOptionId(n);
7649 EXCEPTION
7650 WHEN OTHERS THEN
7651 errorMessage := 'Unknown';
7652 END;
7653
7654 RAISE CZ_R_DELETED_OPTION;
7655 END IF;
7656
7657 IF(NOT v_OptionExists.EXISTS(v_tOptionId(n)))THEN
7658
7659 nDebug := 5000203;
7660
7661 v_ItemLines(itemCount) := GENERATE_NAME(vBackIndex(i), v_tOptionId(n)) || ' ' || TO_CHAR(i - 1);
7662 v_OptionsUsed(itemCount) := v_tOptionId(n);
7663 v_OptionExists(v_tOptionId(n)) := itemCount;
7664 itemCount := itemCount + 1;
7665
7666 END IF;
7667
7668 nDebug := 5000204;
7669
7670 itemIndex := v_OptionExists(v_tOptionId(n));
7671 v_RowLinesIndex(n) := n;
7672
7673 IF(v_RowLines.EXISTS(n))THEN
7674 v_RowLines(n) := v_RowLines(n) || ' ' || TO_CHAR(itemIndex - 1);
7675 ELSE
7676 v_RowLines(n) := ' ' || TO_CHAR(itemIndex - 1);
7677 END IF;
7678
7679 END LOOP;
7680
7681 v_ExcludesRequired(i) := 0;
7682
7683 nDebug := 5000205;
7684
7685 IF(featOptionsCount(vGridColumns(i)) <> itemCount - startCount)THEN
7686
7687 v_StartOptionsUsed(i) := startCount;
7688 v_EndOptionsUsed(i) := itemCount - 1;
7689 v_ExcludesRequired(i) := 1;
7690
7691 END IF;
7692 END LOOP; --Validation and initial data for features
7693
7694 --Design chart rule specific validation - uniqueness of every column in the chart table.
7695 --At the current step this requirement is equivalent to the requirement of no duplicate
7696 --elements in v_RowLines table. We use the modified QuickSort algorythm to sort out the
7697 --table and then check for duplicate values in one pass.
7698
7699 IF(inSuffix = 0)THEN --This is the defining table
7700
7701 --We need a substring of the row starting with the 4th character
7702
7703 FOR i IN 1..v_RowLines.COUNT LOOP
7704 v_tailRowLines(i) := SUBSTR(v_RowLines(i),4);
7705 END LOOP;
7706
7707 SORT_ARRAY_INDEX(1, v_tailRowLines.COUNT);
7708 FOR i IN 2..v_tailRowLines.COUNT LOOP
7709 IF(v_tailRowLines(v_RowLinesIndex(i)) = v_tailRowLines(v_RowLinesIndex(i - 1)))THEN
7710
7711 --Duplicate combination of defining options for a primary option
7712 RAISE CZ_R_DUPLICATE_COMBINATION;
7713
7714 END IF;
7715 END LOOP;
7716 END IF; --This is the defining table
7717
7718 nDebug := 5000206;
7719
7720 FOR i IN 1..vGridColumns.COUNT LOOP
7721
7722 nDebug := 5000207;
7723
7724 IF(v_ExcludesRequired(i) = 1)THEN
7725
7726 nChild := glIndexByPsNodeId(vGridColumns(i)) + 1;
7727
7728 vLogicLine := 'GS E ... ' || TO_CHAR(nReasonId) || NewLine || 'GL N ';
7729 PACK;
7730
7731 nDebug := 5000208;
7732
7733 WHILE(glParentId.EXISTS(nChild) AND glParentId(nChild) = vGridColumns(i))LOOP
7734 IF(OPTION_EXISTS(i) = 0)THEN
7735 vLogicLine := GENERATE_NAME(vBackIndex(i), glPsNodeId(nChild)) || ' ';
7736 PACK;
7737 END IF;
7738 nChild := nChild + 1;
7739 END LOOP;
7740
7741 vLogicLine := NewLine || 'GR L ';
7742 PACK;
7743
7744 nDebug := 5000209;
7745
7746 FOR n IN 1..vGridColumns.COUNT LOOP
7747 IF(n <> i)THEN
7748 vLogicLine := GENERATE_NAME(vBackIndex(n), vGridColumns(n)) || ' ';
7749 PACK;
7750 END IF;
7751 END LOOP;
7752
7753 vLogicLine := NewLine;
7754 PACK;
7755 END IF; --Excludes required
7756 END LOOP;
7757
7758 nDebug := 5000210;
7759
7760 vLogicLine := 'OBJECT P_R' || TO_CHAR(nRuleId) || '_' || TO_CHAR(inSuffix) || NewLine ||
7761 'COMBO P_R' || TO_CHAR(nRuleId) || '_' || TO_CHAR(inSuffix) || ' ' || TO_CHAR(v_ItemLines.COUNT) || ' ' ||
7762 TO_CHAR(v_RowLines.COUNT) || ' ' || TO_CHAR(vGridColumns.COUNT) || ' ... ' ||
7763 TO_CHAR(nReasonId) || NewLine;
7764 PACK;
7765
7766 nDebug := 5000211;
7767
7768 FOR i IN 1..v_ItemLines.COUNT LOOP
7769
7770 vLogicLine := 'CI ' || TO_CHAR(i - 1) || ' ' || v_ItemLines(i) || NewLine;
7771 PACK;
7772
7773 END LOOP;
7774
7775 nDebug := 5000212;
7776
7777 FOR i IN 1..vGridColumns.COUNT LOOP
7778
7779 IF(GenerateGatedCombo = 0)THEN
7780
7781 IF(inSuffix = 0 OR i = 1)THEN
7782
7783 --This is the defining table or the primary feature in an optional table.
7784 --In this case we currently use actual feature's maximum value for the column
7785 --(or maximum_selected for BOM).
7786
7787 --Use intermediate variable instead of using NVL because this is faster
7788
7789 localNumber := glIndexByPsNodeId(vGridColumns(i));
7790 localString := TO_CHAR(glMaximum(localNumber));
7791
7792 --If it's a BOM item, we use maximum_selected instead of maximum
7793
7794 IF(glPsNodeType(localNumber) IN (PS_NODE_TYPE_BOM_MODEL,PS_NODE_TYPE_BOM_OPTIONCLASS,PS_NODE_TYPE_BOM_STANDARD))THEN
7795 localString := TO_CHAR(glMaximumSel(localNumber));
7796 END IF;
7797
7798 IF(localString IS NULL)THEN localString := '-1'; END IF;
7799
7800 ELSE
7801 --For optional features in optional tables we always use '-1' for columns' maximum value.
7802
7803 localString := '-1';
7804 END IF;
7805
7806 vLogicLine := ' O';
7807 ELSE
7808
7809 --Generate gated combinations: maximum is always -1, the 'G' argument is followed
7810 --by the feature name.
7811
7812 localString := '-1';
7813 vLogicLine := ' G ' || GENERATE_NAME(vBackIndex(i), vGridColumns(i));
7814 END IF;
7815
7816 vLogicLine := 'CC ' || TO_CHAR(i - 1) || ' 0 ' || localString || vLogicLine || NewLine;
7817 PACK;
7818
7819 END LOOP;
7820
7821 nDebug := 5000213;
7822
7823 FOR i IN 1..v_RowLines.COUNT LOOP
7824
7825 vLogicLine := 'CR ' || TO_CHAR(i - 1) || v_RowLines(i) || NewLine;
7826 PACK;
7827
7828 END LOOP;
7829
7830 nDebug := 5000214;
7831
7832 vLogicLine := 'COMBO_END' || NewLine;
7833 PACK;
7834 END;
7835 ---------------------------------------------------------------------------------------
7836 BEGIN
7837
7838 --Generate the defining table
7839
7840 nIndex := 2;
7841
7842 FOR i IN expressionStart..expressionEnd LOOP
7843
7844 IF(v_tFeatureType(i) = FEATURE_TYPE_DEFINING)THEN
7845 vGridColumns(nIndex) := v_tExprPsNodeId(i);
7846 vBackIndex(nIndex) := i;
7847 nIndex := nIndex + 1;
7848 ELSIF(v_tFeatureType(i) = FEATURE_TYPE_PRIMARY)THEN
7849 vGridColumns(1) := v_tExprPsNodeId(i);
7850 vBackIndex(1) := i;
7851 END IF;
7852
7853 END LOOP;
7854
7855 IF(vGridColumns.COUNT = 0)THEN
7856 RAISE CZ_R_NO_PRIMARY_FEATURE;
7857 ELSIF(vGridColumns.COUNT > 1)THEN
7858 GENERATE_COMPAT_TEMPLATE(0);
7859 vGridColumns.DELETE(2, vGridColumns.COUNT);
7860 vBackIndex.DELETE(2, vBackIndex.COUNT);
7861 END IF;
7862
7863 --Generate all the optional tables
7864
7865 nIndex := 1;
7866
7867 FOR i IN expressionStart..expressionEnd LOOP
7868
7869 IF(v_tFeatureType(i) = FEATURE_TYPE_OPTIONAL)THEN
7870 vGridColumns(2) := v_tExprPsNodeId(i);
7871 vBackIndex(2) := i;
7872 GENERATE_COMPAT_TEMPLATE(nIndex);
7873 nIndex := nIndex + 1;
7874 END IF;
7875
7876 END LOOP;
7877 END;
7878 ---------------------------------------------------------------------------------------
7879 BEGIN --GENERATE_RULES
7880
7881 nDebug := 0;
7882
7883 IF(t_RuleId.COUNT = 0)THEN
7884
7885 --This should be done only once during the generation session. The data is static and common
7886 --to all models.
7887
7888 SELECT rule_id, signature_id, name BULK COLLECT INTO t_RuleId, t_SignatureId, t_RuleName
7889 FROM cz_rules
7890 WHERE devl_project_id = 0
7891 AND seeded_flag = FLAG_SEEDED
7892 AND deleted_flag = FLAG_NOT_DELETED
7893 AND disabled_flag = FLAG_NOT_DISABLED;
7894
7895 --Make the table of names hashed by rule_id.
7896
7897 FOR i IN 1..t_RuleId.COUNT LOOP
7898
7899 h_SeededName(t_RuleId(i)) := UPPER(t_RuleName(i));
7900 h_ReportName(t_RuleId(i)) := t_RuleName(i);
7901 h_SignatureId(t_RuleId(i)) := t_SignatureId(i);
7902 END LOOP;
7903 END IF;
7904
7905 nDebug := 1;
7906
7907 --Make a quick and simple verification of all functional companions defined in this
7908 --project. All other rule related instances that do not reside in cz_rules can also
7909 --be processed in this section.
7910 --Added as a fix for the bug #2200481.
7911
7912 --Restoring this block in 11.5.10+, bug #3989382.
7913
7914 FOR c_func IN (SELECT component_id, model_ref_expl_id, program_string, name, rule_folder_id
7915 FROM cz_func_comp_specs
7916 WHERE devl_project_id = inComponentId
7917 AND deleted_flag = FLAG_NOT_DELETED) LOOP
7918
7919 IF(c_func.component_id IS NULL)THEN
7920
7921 --'Incomplete data: No base component specified for functional companion ''%COMPANION'' in model ''%MODELNAME''.'
7922 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);
7923
7924 ELSIF(c_func.program_string IS NULL)THEN
7925
7926 --'Incomplete data: No program string specified for functional companion ''%COMPANION'' in model ''%MODELNAME''.'
7927 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);
7928
7929 ELSIF(NOT glIndexByPsNodeId.EXISTS(c_func.component_id))THEN
7930
7931 --'Internal data error. Incorrect product structure data for functional companion ''%COMPANION'' in model ''%MODELNAME''.'
7932 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);
7933
7934 ELSIF(c_func.model_ref_expl_id IS NULL OR (NOT v_IndexByNodeId.EXISTS(c_func.model_ref_expl_id)))THEN
7935
7936 --'Internal data error. Incorrect explosion data for functional companion ''%COMPANION'' in model ''%MODELNAME''.'
7937 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);
7938 END IF;
7939 END LOOP;
7940
7941 --Calculate downpathes for all explosion nodes here
7942
7943 nDebug := 1000007;
7944
7945 FOR i IN 1..v_NodeId.COUNT LOOP
7946
7947 nDebug := 1000002;
7948
7949 --Unconditionally create rule files for all the non-virtual components of the
7950 --model primary structure and all first-level reference nodes and put the INC
7951 --relation there.
7952
7953 IF(v_tVirtualFlag(i) = FLAG_NON_VIRTUAL AND v_tNodeDepth(i) > 0 AND
7954 (v_tChildModelExpl(i) IS NULL OR
7955 (v_tNodeType(i) = PS_NODE_TYPE_REFERENCE AND
7956 v_tChildModelExpl(v_IndexByNodeId(v_tParentId(i))) IS NULL)
7957 ))THEN
7958
7959 nDebug := 1000003;
7960
7961 nHeaderId := next_lce_header_id;
7962
7963 BEGIN
7964
7965 nDebug := 1000004;
7966
7967 --Insert the rule net logic header record into the table.
7968
7969 INSERT INTO cz_lce_headers
7970 (lce_header_id, gen_version, gen_header, component_id, net_type,
7971 devl_project_id, model_ref_expl_id, nbr_required_expls, deleted_flag)
7972 VALUES
7973 (nHeaderId, VersionString, GenHeader, v_tPsNodeId(i), LOGIC_NET_TYPE_MANDATORY,
7974 thisProjectId, v_NodeId(i), 1, FLAG_PENDING);
7975
7976 INSERT INTO cz_lce_load_specs
7977 (attachment_expl_id, lce_header_id, required_expl_id, attachment_comp_id,
7978 model_id, net_type, deleted_flag)
7979 VALUES
7980 (v_NodeId(i), nHeaderId, v_NodeId(i), v_tPsNodeId(i), thisProjectId,
7981 LOGIC_NET_TYPE_MANDATORY, FLAG_PENDING);
7982
7983 EXCEPTION
7984 WHEN OTHERS THEN
7985 errorMessage := SQLERRM;
7986 RAISE CZ_R_UNABLE_TO_CREATE_HEADER;
7987 END;
7988
7989 nDebug := 1000005;
7990
7991 NewHeaders(counterNewHeaders) := nHeaderId;
7992 NewHeadersComponents(counterNewHeaders) := v_tPsNodeId(i);
7993 NewHeadersExplosions(counterNewHeaders) := v_NodeId(i);
7994 counterNewHeaders := counterNewHeaders + 1;
7995
7996 nDebug := 1000006;
7997
7998 --Use intermediate variable instead of using NVL because this is faster
7999
8000 IF(v_tReferringId(i) IS NOT NULL)THEN
8001 localString := TO_CHAR(glPersistentId(v_tReferringId(i)));
8002 ELSE
8003 localString := TO_CHAR(glPersistentId(v_tPsNodeId(i)));
8004 END IF;
8005
8006 vLogicLine := 'CONTROL NOSPEC' || NewLine || 'VERSION 3 3' || NewLine || NewLine ||
8007 'REM -- Rules file for component: ' || TO_CHAR(v_tPsNodeId(i)) ||
8008 ', explosion node: ' || TO_CHAR(v_NodeId(i)) || NewLine || NewLine ||
8009 'EFF , , ' || NewLine || NewLine ||
8010 'INC 1 ' || PATH_DELIMITER || 'parent' || PATH_DELIMITER || 'P_' ||
8011 localString || '_ACTUALCOUNT round' || NewLine;
8012
8013 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES (nHeaderId, 1, vLogicLine);
8014
8015 v_tIsHeaderGenerated(v_NodeId(i)) := nHeaderId;
8016 v_tSequenceNbr(nHeaderId) := 2;
8017 v_tLogicNetType(nHeaderId) := LOGIC_NET_TYPE_MANDATORY;
8018
8019 --This variable is not supposed to be used as an accumulator for logic text. Instead, it
8020 --is used as a buffer every time to store a piece of text to be accumulated in vLogicText
8021 --(see PACK procedure). Therefore, it should be safe to null it out here even if it's not
8022 --necessary.
8023
8024 vLogicLine := NULL;
8025 END IF;
8026
8027 nDebug := 1000008;
8028
8029 --Here we will construct model level downpaths, which do not depend on a particular rule,
8030 --but only on explosion id within the model's explosion tree. When a particular rule is
8031 --assigned, downpaths of its participants may be prepended with segments including all A
8032 --type nodes from assignee to assignable. This corrected downpaths are always used when
8033 --generating names of the rule's participants.
8034
8035 nAux := v_NodeId(i);
8036 auxIndex := v_tNodeDepth(i) + 1;
8037
8038 IF(NOT v_NodeDownPath.EXISTS(nAux))THEN
8039
8040 nDebug := 1000009;
8041
8042 v_NodeDownPath(nAux) := ''; --start building the downpath
8043 v_NodeIndexPath.DELETE; --reset the table
8044
8045 --These all are index values in v_NodeIndexPath.
8046
8047 ConnectorIndex := 0;
8048 InstantiableIndex := auxIndex;
8049 OptionalIndex := auxIndex;
8050 TrackableIndex := auxIndex;
8051 nCounter := 1;
8052 auxCount := 0;
8053
8054 --Go all the way up from the explosion id and find the deepest D node and the
8055 --shallowest connector, and also the deepest optional node.
8056 --We are interested in the shallowest reference to a trackable model as well.
8057 --It will be used only if the root model is marked as a network container. If
8058 --there is no such reference above the explosion node the root node is used.
8059
8060 WHILE(nAux IS NOT NULL) LOOP
8061
8062 localCount := v_IndexByNodeId(nAux);
8063
8064 --Detect infinite loops which may be caused by data corruption.
8065
8066 auxCount := auxCount + 1;
8067 IF(auxCount > LOOP_DETECTED_LOOPS_NUMBER)THEN
8068
8069 errorMessage := glName(glIndexByPsNodeId(inProjectId));
8070 RAISE CZ_G_INVALID_MODEL_EXPLOSION;
8071 END IF;
8072
8073 --The next IF statement has been added as a fix for the bug #2802049. In case of circular
8074 --connectors it is possible that the explosion table of the second level-referenced model
8075 --contains pointers to ps node structure of the parent model that hasn't been read yet.
8076 --As in this case we do not need to generate downpaths, we can just ignore such pointers.
8077
8078 IF(NOT glIndexByPsNodeId.EXISTS(NVL(v_tReferringId(localCount), v_tPsNodeId(localCount))))THEN
8079
8080 auxCount := -1;
8081 EXIT;
8082 END IF;
8083
8084 IF(v_TypeByExplId(nAux) = EXPL_NODE_TYPE_CONNECTOR)THEN
8085
8086 ConnectorIndex := nCounter;
8087 ELSIF(v_TypeByExplId(nAux) = EXPL_NODE_TYPE_OPTIONAL AND OptionalIndex = auxIndex)THEN
8088
8089 OptionalIndex := nCounter;
8090 ELSIF(v_TypeByExplId(nAux) = EXPL_NODE_TYPE_INSTANTIABLE)THEN
8091
8092 IF(InstantiableIndex = auxIndex)THEN InstantiableIndex := nCounter; END IF;
8093
8094 IF(v_tNodeType(localCount) = PS_NODE_TYPE_REFERENCE AND
8095 glIbTrackable(v_tPsNodeId(localCount)) = FLAG_IB_TRACKABLE)THEN
8096
8097 TrackableIndex := nCounter;
8098 END IF;
8099 END IF;
8100
8101 v_NodeIndexPath(nCounter) := localCount;
8102 nCounter := nCounter + 1;
8103
8104 nAux := v_tParentId(localCount);
8105 END LOOP;
8106
8107 IF(auxCount = -1)THEN
8108
8109 --This is the 'circular connectors' case, we don't need any downpath.
8110 NULL;
8111
8112 ELSIF(InstantiableIndex < ConnectorIndex)THEN
8113
8114 --There are D nodes under connectors on the path - this explosion cannot participate
8115 --in any rule because it would be impossible to assign such a rule. No downpath.
8116 --For reporting purposes store the cz_ps_nodes indexes of the instantiable component
8117 --and the connector, corresponding exception/message is CZ_R_UNASSIGNABLE_RULE.
8118
8119 v_ProhibitInRules(v_NodeId(i)) := glIndexByPsNodeId(v_tPsNodeId(v_NodeIndexPath(InstantiableIndex)));
8120 v_ProhibitConnector(v_NodeId(i)) := glIndexByPsNodeId(v_tReferringId(v_NodeIndexPath(ConnectorIndex)));
8121
8122 ELSIF(OptionalIndex < ConnectorIndex)THEN
8123
8124 --There are A nodes under connectors on the path - this explosion cannot participate
8125 --in any rule - bug #2217450. No downpath.
8126 --For reporting purposes store the cz_ps_nodes indexes of the optional component
8127 --and the connector, corresponding exception/message is CZ_R_OPTIONAL_INSIDE.
8128
8129 v_ProhibitOptional(v_NodeId(i)) := glIndexByPsNodeId(v_tPsNodeId(v_NodeIndexPath(OptionalIndex)));
8130 v_ProhibitConnector(v_NodeId(i)) := glIndexByPsNodeId(v_tReferringId(v_NodeIndexPath(ConnectorIndex)));
8131
8132 ELSE
8133
8134 nDebug := 1000010;
8135
8136 AssignableIndex := InstantiableIndex;
8137
8138 --Find the deepest A node between the deepest D node and the shallowest connector.
8139 --This node is the assignable for the explosion id (can be the D node itself).
8140
8141 FOR n IN ConnectorIndex + 1..InstantiableIndex LOOP
8142 IF(v_tExplNodeType(v_NodeIndexPath(n)) = EXPL_NODE_TYPE_OPTIONAL)THEN
8143
8144 AssignableIndex := n;
8145 EXIT;
8146 END IF;
8147 END LOOP;
8148
8149 v_NodeLogicLevel(v_NodeId(i)) := v_tNodeDepth(v_NodeIndexPath(AssignableIndex));
8150
8151 --Store the main index of the assignable of the explosion node.
8152
8153 v_NodeAssignable(v_NodeId(i)) := v_NodeIndexPath(AssignableIndex);
8154
8155 --Store the main index of the deepest instantiable component above the explosion
8156 --node (may be the node itself if it is instantiable, or the root node if there
8157 --is no instantiable components on the way up from the explosion node).
8158
8159 v_NodeInstantiable(v_NodeId(i)) := v_NodeIndexPath(InstantiableIndex);
8160
8161 --Store the main index of the shallowest reference to a trackable model.
8162
8163 v_NodeTrackable(v_NodeId(i)) := v_NodeIndexPath(TrackableIndex);
8164
8165 nDebug := 1000011;
8166
8167 --Finally, construct the downpath from the assignable to the explosion id.
8168
8169 FOR n IN 1..AssignableIndex - 1 LOOP
8170 IF(v_tExplNodeType(v_NodeIndexPath(n)) IN (EXPL_NODE_TYPE_OPTIONAL, EXPL_NODE_TYPE_MANDATORY))THEN
8171
8172 --This is a mandatory reference or optional component, add N_<persistent_node_id>
8173 --to the path.
8174
8175 v_NodeDownPath(v_NodeId(i)) := PATH_DELIMITER || 'N_' ||
8176 TO_CHAR(glPersistentId(NVL(v_tReferringId(v_NodeIndexPath(n)), v_tPsNodeId(v_NodeIndexPath(n))))) ||
8177 v_NodeDownPath(v_NodeId(i));
8178
8179 ELSIF(v_tExplNodeType(v_NodeIndexPath(n)) = EXPL_NODE_TYPE_CONNECTOR)THEN
8180
8181 --This is a connector, add C_<model_ref_expl_id> to the path.
8182
8183 v_NodeDownPath(v_NodeId(i)) := PATH_DELIMITER || 'C_' ||
8184 TO_CHAR(v_NodeId(v_NodeIndexPath(n))) || v_NodeDownPath(v_NodeId(i));
8185
8186 --We will stop here, we do not want anything above the deepest connector to be reflected
8187 --in the path. Set a flag for this explosion because we do not want to prepend downpaths
8188 --for these explosions after the rule is assigned either. Actually, not just a flag, but
8189 --store the connector itself (main index) which may be useful for reporting purposes.
8190
8191 v_IsConnectorNet(v_NodeId(i)) := v_NodeIndexPath(n);
8192 EXIT;
8193 END IF;
8194 END LOOP;
8195 END IF;
8196 END IF;
8197 END LOOP;
8198
8199 nDebug := 2;
8200
8201 OPEN c_rules;
8202 LOOP
8203 BEGIN
8204
8205 --To generate effectivity information for the first rule. Uses the fact that
8206 --effective mask can not be null.
8207
8208 vUsageMask := NULL;
8209
8210 FETCH c_rules INTO
8211 nRuleId, nRuleType, nAntecedentId, nConsequentId, vRuleName, nReasonId, nRuleOperator,
8212 nRuleFolderId, nComponentId, nModelRefExplId, dEffFrom, dEffUntil, vUsageMask,
8213 nRuleEffSetId, nUnsatisfiedId, nUnsatisfiedSource, nPresentationFlag, vClassName;
8214 EXIT WHEN c_rules%NOTFOUND;
8215
8216 --Do nothing for those rules.
8217
8218 IF(nRuleType NOT IN (RULE_TYPE_FUNC_COMP, RULE_TYPE_RULE_FOLDER, RULE_TYPE_BINDING_RULE,
8219 RULE_TYPE_RULE_SYS_PROP, RULE_TYPE_JAVA_SYS_PROP,
8220 RULE_TYPE_CAPTION_RULE, RULE_TYPE_DISPLAY_CONDITION))THEN
8221
8222 v_tExplNodeId.DELETE;
8223 v_tExprType.DELETE;
8224 v_tExprSubtype.DELETE;
8225 v_tExprId.DELETE;
8226 v_tExprParentId.DELETE;
8227 v_tExprTemplateId.DELETE;
8228 v_tExpressId.DELETE;
8229 v_tExprPsNodeId.DELETE;
8230 v_tRealPsNodeId.DELETE;
8231 v_tExprDataValue.DELETE;
8232 v_tExprPropertyId.DELETE;
8233 v_tConsequentFlag.DELETE;
8234 v_tExprParamIndex.DELETE;
8235 v_tExprArgumentName.DELETE;
8236 v_tExprDataType.DELETE;
8237 v_tExprDataNumValue.DELETE;
8238 v_tExprArgSignature.DELETE;
8239 v_tExprParSignature.DELETE;
8240 v_tArgumentIndex.DELETE;
8241 v_tDataType.DELETE;
8242 v_tArgumentName.DELETE;
8243 v_InstByLevel.DELETE;
8244 v_Assignable.DELETE;
8245 v_Participant.DELETE;
8246 v_DistinctIndex.DELETE;
8247 v_ParticipantIndex.DELETE;
8248 v_RuleConnectorNet.DELETE;
8249 v_LevelCount.DELETE;
8250 v_LevelIndex.DELETE;
8251 v_LevelType.DELETE;
8252 v_MarkLoadCondition.DELETE;
8253 v_LoadConditionId.DELETE;
8254 v_ChildrenIndex.DELETE;
8255 v_NodeUpPath.DELETE;
8256 v_IndexByExprNodeId.DELETE;
8257 v_NumberOfChildren.DELETE;
8258 v_ExplByPsNodeId.DELETE;
8259 v_RelativeNodePath.DELETE;
8260 parameterScope.DELETE;
8261 parameterName.DELETE;
8262
8263 jAntecedentRoot := NULL;
8264 jConsequentRoot := NULL;
8265 sUnsatisfiedId := NULL;
8266 RuleTemplateType := RULE_TYPE_UNKNOWN;
8267 numericLHS := 0;
8268 generateCompare := 0;
8269 t_prefix := 'T' || TO_CHAR(nRuleId) || '_';
8270
8271 --We need to reset the assigned down paths for every rule. Bug #3431166.
8272
8273 FOR i IN 1..v_NodeId.COUNT LOOP
8274
8275 --Make a copy that will be used as a rule-specific downpath which may have to be prepended
8276 --after the rule is assigned. It is this copy that will be used for name generation.
8277
8278 v_AssignedDownPath(v_NodeId(i)) := v_NodeDownPath(v_NodeId(i));
8279 END LOOP;
8280
8281 --Bug #3180819.
8282
8283 IF(nPresentationFlag IS NULL)THEN nPresentationFlag := FLAG_FREEFORM_RULE; END IF;
8284
8285 nDebug := 3;
8286
8287 --Get the rule participants, differently for different types of rules
8288
8289 IF(nRuleType = RULE_TYPE_JAVA_METHOD)THEN
8290
8291 --This is a CX. Call the CX validation procedure and continue with rules.
8292
8293 localRunId := thisRunId;
8294 cz_developer_utils_pvt.verify_special_rule(nRuleId, vRuleName, localRunId);
8295 RAISE CZ_LCE_CONTINUE;
8296
8297 ELSIF(nRuleType IN (RULE_TYPE_TEMPLATE, RULE_TYPE_EXPRESSION))THEN
8298
8299 --Set the unsatisfied message id string.
8300
8301 IF(nUnsatisfiedSource <> UNSATISFIED_TYPE_NONE)THEN
8302
8303 sUnsatisfiedId := TO_CHAR(nUnsatisfiedId);
8304 IF(sUnsatisfiedId IS NOT NULL)THEN sUnsatisfiedId := sUnsatisfiedId || ' '; END IF;
8305 END IF;
8306
8307 SELECT model_ref_expl_id, expr_type, expr_node_id, expr_parent_id, template_id,
8308 express_id, expr_subtype, ps_node_id, data_value, property_id, consequent_flag,
8309 param_index, argument_name, data_type, data_num_value, param_signature_id,
8310 relative_node_path
8311 BULK COLLECT INTO v_tExplNodeId, v_tExprType, v_tExprId, v_tExprParentId, v_tExprTemplateId,
8312 v_tExpressId, v_tExprSubtype, v_tExprPsNodeId, v_tExprDataValue,
8313 v_tExprPropertyId, v_tConsequentFlag, v_tExprParamIndex, v_tExprArgumentName,
8314 v_tExprDataType, v_tExprDataNumValue, v_tExprParSignature,
8315 v_RelativeNodePath
8316 FROM cz_expression_nodes
8317 WHERE rule_id = nRuleId
8318 AND expr_type <> EXPR_NODE_TYPE_PUNCT
8319 AND deleted_flag = FLAG_NOT_DELETED
8320 ORDER BY expr_parent_id, seq_nbr;
8321
8322 --Determine the size of the expression for all eventual purposes.
8323
8324 expressionSize := v_tExprType.COUNT;
8325
8326 IF(expressionSize = 0)THEN
8327 RAISE CZ_R_NO_PARTICIPANTS;
8328 END IF;
8329
8330 expressionStart := 1;
8331 expressionEnd := expressionSize;
8332
8333 FOR i IN expressionStart..expressionEnd LOOP
8334
8335 IF(v_tExprDataNumValue(i) IS NOT NULL)THEN v_tExprDataValue(i) := TO_CHAR(v_tExprDataNumValue(i)); END IF;
8336
8337 --Bug #3800352. Resolve the codes by names and emulate regular node types.
8338
8339 IF(v_tExprType(i) IN (EXPR_PROPERTYBYNAME, EXPR_OPERATORBYNAME, EXPR_JAVAPROPERTYBYNAME))THEN
8340
8341 FOR n IN 1..t_RuleId.COUNT LOOP
8342
8343 IF(t_RuleName(n) = v_tExprArgumentName(i))THEN v_tExprTemplateId(i) := t_RuleId(n); EXIT; END IF;
8344 END LOOP;
8345
8346 IF(v_tExprType(i) = EXPR_PROPERTYBYNAME)THEN
8347
8348 v_tExprType(i) := EXPR_SYS_PROP;
8349 ELSIF(v_tExprType(i) = EXPR_OPERATORBYNAME)THEN
8350
8351 v_tExprType(i) := EXPR_OPERATOR;
8352 ELSIF(v_tExprType(i) = EXPR_JAVAPROPERTYBYNAME)THEN
8353
8354 v_tExprType(i) := EXPR_JAVA_PROPERTY;
8355 END IF;
8356 END IF;
8357
8358 --Populate the expression node subtype from template_id for all expression nodes for backward
8359 --compatibility.
8360
8361 v_tExprSubtype(i) := v_tExprTemplateId(i);
8362
8363 --Use the code lookup to fix irregularities in new codes. May become unnecessary when real
8364 --metadata lookup is implemented.
8365
8366 IF(CodeByCodeLookup.EXISTS(v_tExprTemplateId(i)))THEN
8367
8368 v_tExprSubtype(i) := CodeByCodeLookup(v_tExprTemplateId(i));
8369 v_tExprTemplateId(i) := v_tExprSubtype(i);
8370 END IF;
8371
8372 IF(v_tExprParentId(i) IS NOT NULL)THEN
8373
8374 IF(v_NumberOfChildren.EXISTS(v_tExprParentId(i)))THEN
8375 v_NumberOfChildren(v_tExprParentId(i)) := v_NumberOfChildren(v_tExprParentId(i)) + 1;
8376 ELSE
8377 v_NumberOfChildren(v_tExprParentId(i)) := 1;
8378 END IF;
8379
8380 IF(NOT v_ChildrenIndex.EXISTS(v_tExprParentId(i)))THEN
8381 v_ChildrenIndex(v_tExprParentId(i)) := i;
8382 END IF;
8383 END IF;
8384
8385 --If this rule is against max of some component, mark this component as having such a rule.
8386 --Later we will generate INC for this component's actual max.
8387
8388 IF(v_tExprType(i) = EXPR_SYS_PROP AND h_SeededName.EXISTS(v_tExprSubtype(i)) AND
8389 h_SeededName(v_tExprSubtype(i)) = RULE_SYS_PROP_MAXINSTANCE AND
8390 v_tConsequentFlag(i) = FLAG_IS_CONSEQUENT)THEN
8391
8392 v_MaxRuleExists(v_tExplNodeId(i)) := 1;
8393 END IF;
8394
8395 --Add the indexing option.
8396
8397 v_IndexByExprNodeId(v_tExprId(i)) := i;
8398 END LOOP;
8399
8400 ELSIF(nRuleType = RULE_TYPE_COMPAT_TABLE)THEN
8401
8402 --Read all the features
8403
8404 SELECT model_ref_expl_id, feature_id, EXPR_NODE_TYPE_NODE
8405 BULK COLLECT INTO v_tExplNodeId, v_tExprPsNodeId, v_tExprType
8406 FROM cz_des_chart_features
8407 WHERE rule_id = nRuleId
8408 AND deleted_flag = FLAG_NOT_DELETED;
8409
8410 nDebug := 32;
8411
8412 --Determine the size of the expression for all eventual purposes.
8413
8414 expressionSize := v_tExprType.COUNT;
8415
8416 IF(expressionSize < 2)THEN
8417 RAISE CZ_R_NO_PARTICIPANTS;
8418 END IF;
8419
8420 expressionStart := 1;
8421 expressionEnd := expressionSize;
8422
8423 ELSIF(nRuleType = RULE_TYPE_DESIGNCHART_RULE)THEN
8424
8425 --Read all the features
8426
8427 SELECT model_ref_expl_id, feature_id, feature_type, EXPR_NODE_TYPE_NODE
8428 BULK COLLECT INTO v_tExplNodeId, v_tExprPsNodeId, v_tFeatureType, v_tExprType
8429 FROM cz_des_chart_features
8430 WHERE rule_id = nRuleId
8431 AND deleted_flag = FLAG_NOT_DELETED;
8432
8433 nDebug := 34;
8434
8435 --Determine the size of the expression for all eventual purposes.
8436
8437 expressionSize := v_tExprType.COUNT;
8438
8439 IF(expressionSize < 2)THEN
8440 RAISE CZ_R_NO_PARTICIPANTS;
8441 END IF;
8442
8443 expressionStart := 1;
8444 expressionEnd := expressionSize;
8445
8446 ELSE
8447
8448 --Unknown rule type. Do nothing for those rules, just go to the next rule.
8449
8450 RAISE CZ_LCE_CONTINUE;
8451 END IF;
8452
8453 --General rule data validation section - all rule types----------------------------Start
8454
8455 FOR i IN expressionStart..expressionEnd LOOP
8456
8457 IF(v_tExprPsNodeId(i) IS NOT NULL)THEN
8458 IF(NOT glIndexByPsNodeId.EXISTS(v_tExprPsNodeId(i)))THEN
8459
8460 nDebug := 35;
8461
8462 --Every participating node must actually exist in the product structure.
8463
8464 RAISE CZ_R_WRONG_EXPRESSION_NODE;
8465
8466 ELSIF(glPsNodeType(glIndexByPsNodeId(v_tExprPsNodeId(i))) = PS_NODE_TYPE_FEATURE AND
8467 glFeatureType(glIndexByPsNodeId(v_tExprPsNodeId(i))) = PS_NODE_FEATURE_TYPE_STRING)THEN
8468
8469 --A text feature cannot participate in any kind of rules.
8470
8471 localString := glName(glIndexByPsNodeId(v_tExprPsNodeId(i)));
8472 RAISE CZ_R_INCORRECT_FEATURE_TYPE;
8473
8474 ELSIF(glPsNodeType(glIndexByPsNodeId(v_tExprPsNodeId(i))) = PS_NODE_TYPE_CONNECTOR)THEN
8475
8476 --A connector cannot participate in any kind of rules.
8477
8478 RAISE CZ_R_CONNECTOR_RULE;
8479 END IF;
8480
8481 IF(v_tExplNodeId(i) IS NULL)THEN
8482
8483 nDebug := 36;
8484
8485 --Every not null ps_node_id should have a not null assosiated model_ref_expl_id (data corruption).
8486
8487 RAISE CZ_G_INVALID_RULE_EXPLOSION;
8488
8489 ELSIF(NOT v_IndexByNodeId.EXISTS(v_tExplNodeId(i)))THEN
8490
8491 nDebug := 37;
8492
8493 --All the participants' model_ref_expl_id must be in the current model's explosion table (data corruption).
8494
8495 RAISE CZ_G_INVALID_RULE_EXPLOSION;
8496
8497 END IF;
8498 END IF;
8499
8500 nDebug := 38;
8501
8502 IF(v_tExprType(i) IN (EXPR_NODE_TYPE_NODE, EXPR_PSNODEBYNAME))THEN
8503 IF(v_tExprPsNodeId(i) IS NULL)THEN
8504
8505 nDebug := 381;
8506
8507 --Every node type node must have assosiated ps_node_id.
8508
8509 RAISE CZ_R_INCORRECT_NODE_ID;
8510 END IF;
8511 ELSIF(v_tExprType(i) = EXPR_NODE_TYPE_LITERAL)THEN
8512 IF(v_tExprDataValue(i) IS NULL)THEN
8513
8514 nDebug := 382;
8515
8516 --Every literal must have not null value.
8517
8518 RAISE CZ_R_LITERAL_NO_VALUE;
8519 END IF;
8520 ELSIF(v_tExprType(i) = EXPR_NODE_TYPE_FEATPROP)THEN
8521 IF(v_tExprPsNodeId(i) IS NULL)THEN
8522
8523 nDebug := 383;
8524
8525 --Every feature property node must have assosiated ps_node_id.
8526
8527 RAISE CZ_R_INCORRECT_NODE_ID;
8528 ELSIF(v_tExprPropertyId(i) IS NULL)THEN
8529
8530 nDebug := 384;
8531
8532 --Every feature property node must have assosiated property_id.
8533
8534 RAISE CZ_R_FEATURE_NO_PROPERTY;
8535 END IF;
8536 END IF;
8537
8538 --Bug #4760372.
8539
8540 IF(v_tExprType(i) = EXPR_PSNODEBYNAME)THEN
8541
8542 --This will resolve the path if possible, populate ps_node_id and model_ref_expl_id with
8543 --resolved values and change the type of the expression node.
8544
8545 RESOLVE_NODE(SPLIT_PATH(v_RelativeNodePath(i)), v_tExprPsNodeId(i), v_tExplNodeId(i), v_tExprPsNodeId(i), v_tExplNodeId(i));
8546 v_tExprType(i) := EXPR_NODE_TYPE_NODE;
8547 END IF;
8548 END LOOP;
8549 --General rule data validation section-----------------------------------------------End
8550
8551 nDebug := 41;
8552
8553 nCounter := 0;
8554 distinctCount := 0;
8555 participantCount := 0;
8556 MaxDepthValue := 0;
8557 MaxDepthIndex := thisRootExplIndex;
8558
8559 FOR i IN expressionStart..expressionEnd LOOP
8560 IF(v_tExprPsNodeId(i) IS NOT NULL)THEN
8561
8562 participantCount := participantCount + 1;
8563 auxIndex := glIndexByPsNodeId(v_tExprPsNodeId(i));
8564
8565 --Soft fix the explosion nodes whenever necessary:
8566
8567 --When a rule has a reference node as a participant,Developer would put the explosion id
8568 --of the reference node itself instead of the explosion id of its parent. This should be
8569 --fixed in some cases (see below).
8570 --If a participant is a component, then it's the component's MIN,MAX or COUNT and actual
8571 --participant should be it's parent. However,it can also be features of the component or
8572 --some other (new) operator. That's why we make sure that the parent of the component is
8573 --the operator DOT and, in addition, the component is non-virtual.
8574
8575 --Later remark:
8576 --A reference, as well as a component, should be fixed only when they are in combination
8577 --with system property. So, it's not enough to check that the parent operator is DOT, we
8578 --also have to make sure that the another operand is EXPR_SYS_PROP with MIN,MAX or COUNT
8579 --subtype.
8580
8581 IF(glPsNodeType(auxIndex) = PS_NODE_TYPE_REFERENCE OR
8582 (glPsNodeType(auxIndex) = PS_NODE_TYPE_COMPONENT AND glVirtualFlag(auxIndex) = FLAG_NON_VIRTUAL))THEN
8583
8584 IF((v_ChildrenIndex.EXISTS(v_tExprId(i)) AND v_tExprType(v_ChildrenIndex(v_tExprId(i))) = EXPR_SYS_PROP AND
8585 h_SeededName.EXISTS(v_tExprSubtype(v_ChildrenIndex(v_tExprId(i)))) AND
8586 h_SeededName(v_tExprSubtype(v_ChildrenIndex(v_tExprId(i)))) IN (RULE_SYS_PROP_MININSTANCE, RULE_SYS_PROP_MAXINSTANCE, RULE_SYS_PROP_INSTANCECOUNT))
8587 )THEN
8588
8589 --SYS_PROP_COUNT has been removed from the above condition as a part of the fix for the
8590 --bug #2317427 - we do not want to fix explosion if it is a reference to a BOM ATO. For
8591 --such a reference SYS_PROP_COUNT means #Quantity.
8592
8593 --If this is a reference to a trackable model in a network container model, then this
8594 --rule is against its #Min or #Max, not #Quantity, and so it should be prohibited.
8595 --This exception does not just ignore the rule, it stops the generation.
8596
8597 IF(rootProjectType = MODEL_TYPE_CONTAINER_MODEL AND glIbTrackable(v_tExprPsNodeId(i)) = FLAG_IB_TRACKABLE)THEN
8598
8599 nParam := auxIndex;
8600 RAISE CZ_R_AGAINST_TRACKABLE;
8601 END IF;
8602
8603 v_tExplNodeId(i) := v_tParentId(v_IndexByNodeId(v_tExplNodeId(i)));
8604
8605 ELSIF(glPsNodeType(auxIndex) = PS_NODE_TYPE_REFERENCE)THEN
8606
8607 --If we are here, than this is a reference to a BOM model, because it should be prohibited
8608 --for a reference to a component to participate with anything other than it's MIN or MAX.
8609 --We will fix the corresponding PS_NODE_ID value to be not the reference node's PS_NODE_ID
8610 --but the PS_NODE_ID of the referenced BOM model. This is necessary to generate the correct
8611 --object name.
8612 --In some cases we still need to use the real reference's ps_node_id.
8613
8614 v_tRealPsNodeId(i) := v_tExprPsNodeId(i);
8615 v_tExprPsNodeId(i) := glReferenceId(v_tExprPsNodeId(i));
8616 END IF;
8617 END IF;
8618
8619 nDebug := 42;
8620
8621 --Select a participant and get its explosion id.
8622
8623 nAux := v_tExplNodeId(i);
8624
8625 IF(NOT v_Participant.EXISTS(nAux))THEN
8626
8627 nDebug := 43;
8628
8629 IF(v_ProhibitInRules.EXISTS(nAux))THEN
8630
8631 --This explosion node has D nodes under connectors on the way up in the explosion table.
8632 --It will be impossible to assign this rule, so just stop here.
8633
8634 localString := glName(glIndexByPsNodeId(v_tExprPsNodeId(i)));
8635 auxIndex := v_ProhibitInRules(nAux);
8636 auxCount := v_ProhibitConnector(nAux);
8637 RAISE CZ_R_UNASSIGNABLE_RULE;
8638
8639 ELSIF(v_ProhibitOptional.EXISTS(nAux))THEN
8640
8641 --This explosion node has A nodes under connectors on the way up in the explosion table.
8642 --Stop here - bug #2217450.
8643
8644 localString := glName(glIndexByPsNodeId(v_tExprPsNodeId(i)));
8645 auxIndex := v_ProhibitOptional(nAux);
8646 auxCount := v_ProhibitConnector(nAux);
8647 RAISE CZ_R_OPTIONAL_INSIDE;
8648 END IF;
8649
8650 --Add to the list of indexes of distinct participants' explosions.
8651
8652 v_Participant(nAux) := 1;
8653 distinctCount := distinctCount + 1;
8654 v_ParticipantIndex(distinctCount) := v_IndexByNodeId(nAux);
8655
8656 --The node is not prohibited from participating in rules, so both assignable exists and
8657 --corresponding deepest instantiable node is defined.
8658
8659 auxIndex := v_NodeInstantiable(nAux);
8660 auxCount := v_NodeAssignable(nAux);
8661
8662 --We mark the potential assignables to reflect the fact that the associated participant
8663 --belongs to a connector net. We need a separate table because this information is rule
8664 --specific while v_IsConnectorNet stores the explosion-specific information. A node can
8665 --be assignable for a connector's net participant in one rule but not in another.
8666
8667 IF(v_IsConnectorNet.EXISTS(nAux))THEN
8668
8669 v_RuleConnectorNet(auxIndex) := 1;
8670 v_RuleConnectorNet(auxCount) := 1;
8671 END IF;
8672
8673 --Select and store all the distinct assignables for all the current rule's participants.
8674 --Main indexes are stored in v_DistinctIndex. Also find the deepest D node among all of
8675 --participants here. MaxDepthValue is initialized to the root (0), so that if there are
8676 --no D nodes, the root node will act as one.
8677
8678 nDebug := 44;
8679
8680 IF(NOT v_Assignable.EXISTS(auxIndex))THEN
8681
8682 v_Assignable(auxIndex) := 1;
8683 nCounter := nCounter + 1;
8684 v_DistinctIndex(nCounter) := auxIndex;
8685
8686 IF(v_tNodeDepth(auxIndex) > MaxDepthValue)THEN
8687
8688 MaxDepthValue := v_tNodeDepth(auxIndex);
8689 MaxDepthIndex := auxIndex;
8690 END IF;
8691 END IF;
8692
8693 IF(NOT v_Assignable.EXISTS(auxCount))THEN
8694
8695 v_Assignable(auxCount) := 1;
8696 nCounter := nCounter + 1;
8697 v_DistinctIndex(nCounter) := auxCount;
8698 END IF;
8699 END IF; --This is a distinct participant.
8700
8701 v_ExplByPsNodeId(v_tExprPsNodeId(i)) := v_tExplNodeId(i);
8702
8703 END IF; --This is a participant.
8704 END LOOP;
8705
8706 nDebug := 45;
8707
8708 --Now populate the <index in memory>(NODE_DEPTH) table for assignables of any type which
8709 --are above the deepest D component. They should form a chain, without duplicates on the
8710 --same level. Here we verify that there are no two components on the same level. This is
8711 --necessary but not sufficient for the rule to be valid.
8712
8713 FOR i IN 1..v_DistinctIndex.COUNT LOOP
8714
8715 auxIndex := v_DistinctIndex(i);
8716
8717 IF(v_tNodeDepth(auxIndex) <= MaxDepthValue)THEN
8718 IF(v_InstByLevel.EXISTS(v_tNodeDepth(auxIndex)))THEN
8719
8720 --There is already a node on this level. Two or more non-virtual components on the
8721 --same level are prohibited.
8722
8723 auxCount := glIndexByPsNodeId(v_tPsNodeId(auxIndex));
8724 auxIndex := glIndexByPsNodeId(v_tPsNodeId(v_InstByLevel(v_tNodeDepth(auxIndex))));
8725 RAISE CZ_R_CONFLICTING_NODES;
8726 ELSE
8727
8728 --This level is now occupied by a node with memory index auxIndex.
8729
8730 v_InstByLevel(v_tNodeDepth(auxIndex)) := auxIndex;
8731 END IF;
8732 END IF;
8733 END LOOP;
8734
8735 nDebug := 46;
8736
8737 --Now we make sure that if we move up from the deepest D assignable, we will step over
8738 --all other assignable which are above this D, so they all form a chain.
8739 --We start with the deepest D component and move up to its parent and so on thus going
8740 --through every level in the hierarchy. On every level, if an assignable exists there,
8741 --we make sure that this node is what we expect - the parent we just moved up to.
8742
8743 nCounter := 0;
8744 auxIndex := MaxDepthIndex;
8745
8746 LOOP
8747 IF(v_InstByLevel.EXISTS(v_tNodeDepth(auxIndex)))THEN
8748 IF(v_InstByLevel(v_tNodeDepth(auxIndex)) <> auxIndex)THEN
8749
8750 --Incorrect node on the level. The rule goes across non-virual boundaries.
8751
8752 auxCount := glIndexByPsNodeId(v_tPsNodeId(v_InstByLevel(v_tNodeDepth(auxIndex))));
8753 auxIndex := glIndexByPsNodeId(v_tPsNodeId(MaxDepthIndex));
8754 RAISE CZ_R_INCORRECT_NODE_LEVEL;
8755 END IF;
8756 nCounter := nCounter + 1;
8757 END IF;
8758
8759 EXIT WHEN nCounter = v_InstByLevel.COUNT OR v_tParentId(auxIndex) IS NULL;
8760 auxIndex := v_IndexByNodeId(v_tParentId(auxIndex));
8761 END LOOP;
8762
8763 nDebug := 47;
8764
8765 --We verified that on the way up from the deepest D node we pass ONLY through eligible
8766 --assignables. Now lets see if we passed through ALL of them.
8767
8768 IF(nCounter <> v_InstByLevel.COUNT)THEN
8769
8770 --Not all the assignables have been passed on the way up. The rule goes across
8771 --non-virual boundaries.
8772
8773 RAISE CZ_R_INVALID_RULE;
8774 END IF;
8775
8776 --So, there exists the deepest type D assignable (it can be the root node) and we verified
8777 --that above it there is no non-virtual boundaries crossing. However, if there are A type
8778 --assignables beneath that D node, we want to assign the rule to the least common ancestor.
8779 --Or there may be not assignables but just regular A nodes between assignables and D.
8780
8781 --First of all, let us see if there are connector's nets attached to the deepest component
8782 --among the rule participants, because if there are, then the rule will be assigned to the
8783 --deepst D already found and there's no need to work with A type components. Example:
8784
8785 -- M
8786 -- |_D
8787 -- |_A0
8788 -- | |_A
8789 -- | | |_F2
8790 -- | |_A
8791 -- | |_F3
8792 -- |
8793 -- |_Connector->M1-F4
8794
8795 --For both rules relating either (F2, F3) or (F2, F3, F4), D is the deepest D node. However,
8796 --the first rule should be assigned to A0 while the second rule should be assigned to D.
8797 --Reference bug #2188507.
8798
8799 --We also identify possible connector's nets attached to a node above the deepest D node.
8800 --Such explosions will have assignables above the deepest D and so may have passed all the
8801 --tests above, but a rule may still cross non-virual boundaries. Example:
8802
8803 -- M
8804 -- |_D
8805 -- | |_A
8806 -- | |_F2
8807 -- |
8808 -- |___Connector->M1-F4
8809
8810 --F4 has M as its assignable, and although M and D form a good chain, an (F2, F4) rule is
8811 --prohibited.
8812 --Reference bug #2190399.
8813
8814 --This block can be optimized to use v_RuleConnectorNet table which was introduced later.
8815
8816 auxCount := 0;
8817
8818 FOR i IN 1..v_ParticipantIndex.COUNT LOOP
8819
8820 nAux := v_NodeId(v_ParticipantIndex(i));
8821
8822 IF(v_IsConnectorNet.EXISTS(nAux))THEN
8823 IF(v_tNodeDepth(v_NodeAssignable(nAux)) < MaxDepthValue)THEN
8824
8825 --This is a connector's net attached to a node above the deepest D assignable, report
8826 --the rule.
8827
8828 auxCount := glIndexByPsNodeId(v_tReferringId(v_IsConnectorNet(nAux)));
8829 auxIndex := glIndexByPsNodeId(v_tPsNodeId(MaxDepthIndex));
8830 RAISE CZ_R_CONNECTOR_ASIDE;
8831 ELSIF(v_NodeAssignable(nAux) = MaxDepthIndex)THEN
8832
8833 --This is a connector's net attached to the D, so the rule will be assigned to the D.
8834
8835 auxCount := 1;
8836
8837 --Just one attached net is enough, but we cannot exit here because we need to examine
8838 --all other participants on account of connector's nets attached above the D node
8839 --(the previous IF does that).
8840 END IF;
8841 END IF;
8842 END LOOP;
8843
8844 IF(auxCount = 0)THEN
8845
8846 --We know that the rule can be assigned somewhere under the deepest D node. It can be
8847 --one of the A type nodes under the deepest D, assignable or not. We start from every
8848 --assignable A node underneath the deepest D and go up all the way to the D. If we do
8849 --not end up on the deepest D, the rule crosses non-virtual boundaries and is invalid.
8850
8851 --On the way up we collect the following information:
8852
8853 -- for every level the number of distinct components of any type on this level
8854 -- (v_LevelCount);
8855 -- index of the first of such components (v_LevelIndex);
8856 -- type of the first of such components (v_LevelType);
8857
8858 nDebug := 48;
8859
8860 nCounter := MaxDepthValue;
8861
8862 FOR i IN 1..v_DistinctIndex.COUNT LOOP
8863
8864 auxIndex := v_DistinctIndex(i);
8865 nAux := v_tNodeDepth(auxIndex);
8866
8867 IF(v_tExplNodeType(auxIndex) = EXPL_NODE_TYPE_OPTIONAL AND nAux > MaxDepthValue)THEN
8868
8869 IF(nCounter < nAux)THEN nCounter := nAux; END IF;
8870
8871 FOR n IN REVERSE MaxDepthValue + 1..nAux LOOP
8872
8873 IF(NOT v_LevelCount.EXISTS(nAux))THEN
8874
8875 v_LevelCount(nAux) := 1;
8876 v_LevelIndex(nAux) := auxIndex;
8877 v_LevelType(nAux) := v_tExplNodeType(auxIndex);
8878 END IF;
8879
8880 IF(auxIndex <> v_LevelIndex(nAux))THEN
8881
8882 v_LevelCount(nAux) := v_LevelCount(nAux) + 1;
8883 END IF;
8884
8885 auxIndex := v_IndexByNodeId(v_tParentId(auxIndex));
8886 nAux := nAux - 1;
8887 END LOOP;
8888
8889 IF(auxIndex <> MaxDepthIndex)THEN
8890
8891 --The way up from the A node doesn't pass through the D node on level MaxDepthValue.
8892 --Crossing of non-virtual boundaries detected.
8893
8894 auxCount := glIndexByPsNodeId(v_tPsNodeId(v_DistinctIndex(i)));
8895 auxIndex := glIndexByPsNodeId(v_tPsNodeId(MaxDepthIndex));
8896 RAISE CZ_R_OPTIONAL_ASIDE;
8897 END IF;
8898 END IF;
8899 END LOOP;
8900
8901 nDebug := 49;
8902
8903 --We want to find the deepest A component we can assign the rule to. So we move from the
8904 --top down shifting MaxDepthIndex with every A component we find. When we hit a fork, we
8905 --stop.
8906
8907 FOR i IN MaxDepthValue + 1..nCounter LOOP
8908
8909 IF(v_LevelCount(i) = 1 AND v_LevelType(i) = EXPL_NODE_TYPE_OPTIONAL)THEN
8910
8911 MaxDepthIndex := v_LevelIndex(i);
8912 END IF;
8913
8914 --We stop when we hit a fork or when we see that there is a connector net attached to
8915 --the optional component which is another kind of fork. Example:
8916
8917 -- A1
8918 -- |_A2
8919 -- |_A3
8920 -- | |_A4
8921 -- |
8922 -- |_Connector->participant
8923
8924 --We don't want to go below A2.
8925
8926 IF(v_LevelCount(i) > 1 OR v_RuleConnectorNet.EXISTS(v_LevelIndex(i))) THEN
8927
8928 EXIT;
8929 END IF;
8930 END LOOP;
8931 END IF; --We finished processing the tree of A nodes beneath the deepest D node which
8932 --may have resulted in assigning the rule to an A node under the deepest D.
8933
8934 --If this rule is defined in a network container model, it can't have participants across
8935 --instantiable references to trackable models. We have already calculated indexes of such
8936 --references for every explosion. The requirement above means that, if one of the indexes
8937 --belongs to a non-trackable model, then all the indexes should belong to a non-trackable
8938 --model.
8939
8940 IF(rootProjectType = MODEL_TYPE_CONTAINER_MODEL)THEN
8941
8942 localCount := 0;
8943
8944 FOR i IN 1..v_ParticipantIndex.COUNT LOOP
8945
8946 IF(glIbTrackable(v_tPsNodeId(v_NodeTrackable(v_NodeId(v_ParticipantIndex(i))))) = FLAG_NOT_IB_TRACKABLE)
8947 THEN localCount := localCount + 1; END IF;
8948 END LOOP;
8949
8950 IF(localCount > 0 AND localCount < v_ParticipantIndex.COUNT)THEN
8951
8952 RAISE CZ_R_ACROSS_TRACKABLE;
8953 END IF;
8954 END IF;
8955
8956 nDebug := 490;
8957
8958 --The rule is assigned to this component (identified by model_ref_expl_id). This variable
8959 --is used mostly for identification of rule logic files, but also in rule generation code.
8960
8961 MaxDepthId := v_NodeId(MaxDepthIndex);
8962 MaxDepthValue := v_tNodeDepth(MaxDepthIndex);
8963
8964 nDebug := 50;
8965
8966 --We need to prepend downpaths for all the distinct participating explosions. If the
8967 --assignable of an explosion id is deeper than the rule's assignee, we are going to
8968 --prepend the downpath with all optional (type A) components or mandatory references
8969 --on the way down from the assignee to the assignable. We do not need to change the
8970 --node's logic level.
8971 --We do not prepend downpaths for explosions corresponding to connectors.
8972
8973 FOR i IN 1..v_ParticipantIndex.COUNT LOOP
8974
8975 nAux := v_NodeId(v_ParticipantIndex(i));
8976
8977 IF(NOT v_IsConnectorNet.EXISTS(nAux))THEN
8978
8979 auxIndex := v_NodeAssignable(nAux);
8980
8981 WHILE(v_tNodeDepth(auxIndex) > MaxDepthValue)LOOP
8982 IF(v_tExplNodeType(auxIndex) IN (EXPL_NODE_TYPE_OPTIONAL, EXPL_NODE_TYPE_MANDATORY))THEN
8983
8984 v_AssignedDownPath(nAux) := PATH_DELIMITER || 'N_' ||
8985 TO_CHAR(glPersistentId(NVL(v_tReferringId(auxIndex), v_tPsNodeId(auxIndex)))) ||
8986 v_AssignedDownPath(nAux);
8987 END IF;
8988
8989 auxIndex := v_IndexByNodeId(v_tParentId(auxIndex));
8990 END LOOP;
8991 END IF;
8992 END LOOP;
8993
8994 nDebug := 51;
8995
8996 --Now we can go ahead and collect the load conditions for this rule. Those would be all
8997 --type A (optional) and C (connector) descendants of the rule assignee. To collect them
8998 --we need to go up from each (distinct) rule participant's explosion id (index).
8999 --There may also be no load conditions at all and then this is the 'standard' rule file
9000 --identified by explosion id of the assignee as a load condition (NET_TYPE = 2).
9001
9002 FOR i IN 1..v_ParticipantIndex.COUNT LOOP
9003
9004 auxIndex := v_ParticipantIndex(i);
9005
9006 WHILE(v_tNodeDepth(auxIndex) > MaxDepthValue AND v_tParentId(auxIndex) IS NOT NULL) LOOP
9007
9008 IF(v_tExplNodeType(auxIndex) IN (EXPL_NODE_TYPE_OPTIONAL, EXPL_NODE_TYPE_CONNECTOR))THEN
9009
9010 --It is enough to just mark the index as a load condition.
9011
9012 v_MarkLoadCondition(auxIndex) := 1;
9013 END IF;
9014
9015 auxIndex := v_IndexByNodeId(v_tParentId(auxIndex));
9016 END LOOP;
9017 END LOOP;
9018
9019 nDebug := 52;
9020
9021 nHeaderId := NEVER_EXISTS_ID;
9022
9023 IF(v_MarkLoadCondition.COUNT = 0)THEN
9024
9025 --This is going to be a mandatory (standard) rule file.
9026
9027 logicNetType := LOGIC_NET_TYPE_MANDATORY;
9028 v_LoadConditionId(1) := MaxDepthId;
9029 IF(v_tIsHeaderGenerated.EXISTS(MaxDepthId))THEN
9030
9031 nHeaderId := v_tIsHeaderGenerated(MaxDepthId);
9032 END IF;
9033 ELSE
9034
9035 --There are load conditions, so this is going to be a network logic file.
9036
9037 logicNetType := LOGIC_NET_TYPE_NETWORK;
9038
9039 nDebug := 53;
9040
9041 --Generate the load condition string. Note that with the algorithm used condition nodes
9042 --are ordered, otherwise it would make no sense.
9043 --There is currently no check for not to exceed the length of the localString.
9044
9045 localString := NULL;
9046 nCounter := 0;
9047
9048 FOR i IN 1..v_NodeId.COUNT LOOP
9049 IF(v_MarkLoadCondition.EXISTS(i))THEN
9050
9051 nCounter := nCounter + 1;
9052 v_LoadConditionId(nCounter) := v_NodeId(i);
9053 localString := localString || ':' || TO_CHAR(v_NodeId(i));
9054 END IF;
9055 END LOOP;
9056
9057 nDebug := 54;
9058
9059 nCounter := 0;
9060
9061 FOR i IN 1..v_LoadConditions.COUNT LOOP
9062 IF(localString = v_LoadConditions(i))THEN
9063
9064 --Load condition found, fetch the corresponding header and exit the loop.
9065
9066 nHeaderId := v_LoadHeaders(i);
9067 nCounter := 1;
9068 EXIT;
9069 END IF;
9070 END LOOP;
9071
9072 IF(nCounter = 0)THEN
9073
9074 --A new load condition, add it to the table. Corresponding header will be
9075 --generated and added later.
9076
9077 v_LoadConditions(v_LoadConditions.COUNT + 1) := localString;
9078 END IF;
9079 END IF;
9080
9081 nCounter := v_LoadConditionId.COUNT;
9082
9083 nDebug := 7;
9084
9085 --Generate a new logic header if necessary.
9086
9087 IF(nHeaderId = NEVER_EXISTS_ID)THEN
9088
9089 nHeaderId := next_lce_header_id;
9090
9091 BEGIN
9092
9093 --Insert the rule net logic header record into the table.
9094
9095 INSERT INTO cz_lce_headers
9096 (lce_header_id, gen_version, gen_header, component_id, net_type,
9097 devl_project_id, model_ref_expl_id, nbr_required_expls, deleted_flag)
9098 VALUES
9099 (nHeaderId, VersionString, GenHeader, v_tPsNodeId(v_IndexByNodeId(MaxDepthId)),
9100 logicNetType, thisProjectId, MaxDepthId, nCounter, FLAG_PENDING);
9101
9102 FOR i IN 1..nCounter LOOP
9103
9104 nAux := v_LoadConditionId(i);
9105
9106 --The following statement populates the new ALIAS_NAME column introduced as a fix
9107 --for the bug #2214414. The column is populated with C_<model_ref_expl_id> for
9108 --connector conditions and with NULL for other conditions (optional components).
9109
9110 INSERT INTO cz_lce_load_specs
9111 (attachment_expl_id, lce_header_id, required_expl_id, attachment_comp_id,
9112 model_id, net_type, deleted_flag, alias_name)
9113 VALUES
9114 (MaxDepthId, nHeaderId, nAux, v_tPsNodeId(v_IndexByNodeId(MaxDepthId)),
9115 thisProjectId, logicNetType, FLAG_PENDING,
9116 DECODE(v_tExplNodeType(v_IndexByNodeId(nAux)), EXPL_NODE_TYPE_CONNECTOR, 'C_' || nAux, NULL));
9117 END LOOP;
9118
9119 EXCEPTION
9120 WHEN OTHERS THEN
9121 errorMessage := SQLERRM;
9122 RAISE CZ_R_UNABLE_TO_CREATE_HEADER;
9123 END;
9124
9125 NewHeaders(counterNewHeaders) := nHeaderId;
9126 NewHeadersComponents(counterNewHeaders) := v_tPsNodeId(v_IndexByNodeId(MaxDepthId));
9127 NewHeadersExplosions(counterNewHeaders) := MaxDepthId;
9128 counterNewHeaders := counterNewHeaders + 1;
9129
9130 IF(logicNetType = LOGIC_NET_TYPE_MANDATORY)THEN
9131
9132 v_tIsHeaderGenerated(MaxDepthId) := nHeaderId;
9133 ELSE
9134
9135 v_LoadHeaders(v_LoadHeaders.COUNT + 1) := nHeaderId;
9136 END IF;
9137
9138 v_tSequenceNbr(nHeaderId) := 1;
9139 v_tLogicNetType(nHeaderId) := logicNetType;
9140 nNewLogicFileFlag := 1;
9141 END IF;
9142
9143 nRuleAssignedLevel := v_tNodeDepth(v_IndexByNodeId(MaxDepthId));
9144
9145 --If the logic file has changed then we need to flush off the buffer
9146
9147 IF(nHeaderId <> nPreviousHeaderId)THEN
9148
9149 IF(vLogicText IS NOT NULL)THEN
9150 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
9151 (nPreviousHeaderId, v_tSequenceNbr(nPreviousHeaderId), vLogicText);
9152 vLogicText := NULL;
9153 v_tSequenceNbr(nPreviousHeaderId) := v_tSequenceNbr(nPreviousHeaderId) + 1;
9154 END IF;
9155
9156 END IF;
9157
9158 nPreviousHeaderId := nHeaderId;
9159
9160 IF(nNewLogicFileFlag = 1)THEN
9161
9162 --This is a new logic file, put the header lines in
9163
9164 vLogicLine := 'CONTROL NOSPEC' || NewLine || 'VERSION 3 3' || NewLine || NewLine ||
9165 'REM -- Rules file for component: ' || TO_CHAR(v_tPsNodeId(v_IndexByNodeId(MaxDepthId))) ||
9166 ', explosion node: ' || TO_CHAR(MaxDepthId) || NewLine || NewLine;
9167 PACK;
9168 nNewLogicFileFlag := 0;
9169
9170 END IF;
9171
9172 nDebug := 8;
9173
9174 --Prepare the effective date interval.
9175 --First get the effective date interval either from an effectivity set or
9176 --from the local values.
9177
9178 IF(nRuleEffSetId IS NOT NULL)THEN
9179 IF(gvIndexBySetId.EXISTS(nRuleEffSetId))THEN
9180
9181 nDebug := 8000100;
9182
9183 CurrentEffFrom := gvEffFrom(gvIndexBySetId(nRuleEffSetId));
9184 CurrentEffUntil := gvEffUntil(gvIndexBySetId(nRuleEffSetId));
9185 ELSE
9186 --This is a fatal error - data corruption
9187 RAISE CZ_R_WRONG_EFFECTIVITY_SET;
9188 END IF;
9189 ELSE
9190 CurrentEffFrom := dEffFrom;
9191 CurrentEffUntil := dEffUntil;
9192 END IF;
9193
9194 nDebug := 8000101;
9195
9196 --Make sure effective dates are not null. Usage mask is not null anyway.
9197
9198 IF(CurrentEffFrom IS NULL)THEN CurrentEffFrom := EpochBeginDate; END IF;
9199 IF(CurrentEffUntil IS NULL)THEN CurrentEffUntil := EpochEndDate; END IF;
9200
9201 dEffFrom := CurrentEffFrom;
9202 dEffUntil := CurrentEffUntil;
9203
9204 IF((NOT PrevRuleEffFrom.EXISTS(nHeaderId)) OR
9205 (CurrentEffFrom <> PrevRuleEffFrom(nHeaderId)) OR (CurrentEffUntil <> PrevRuleEffUntil(nHeaderId)) OR
9206 (vUsageMask <> PrevRuleUsageMask(nHeaderId)))THEN
9207
9208 vLogicLine := LTRIM(vUsageMask, '0');
9209 IF(vLogicLine IS NOT NULL) THEN
9210 vLogicLine := EffUsagePrefix || vLogicLine;
9211 END IF;
9212
9213 IF(CurrentEffFrom = EpochBeginDate)THEN
9214 CurrentFromDate := NULL;
9215 ELSE
9216 CurrentFromDate := TO_CHAR(CurrentEffFrom, EffDateFormat);
9217 END IF;
9218
9219 IF(CurrentEffUntil = EpochEndDate)THEN
9220 CurrentUntilDate := NULL;
9221 ELSE
9222 CurrentUntilDate := TO_CHAR(CurrentEffUntil, EffDateFormat);
9223 END IF;
9224
9225 vLogicLine := 'EFF ' || CurrentFromDate || ', ' || CurrentUntilDate || ', ' || vLogicLine || NewLine;
9226 PACK;
9227
9228 PrevRuleEffFrom(nHeaderId) := CurrentEffFrom;
9229 PrevRuleEffUntil(nHeaderId) := CurrentEffUntil;
9230 PrevRuleUsageMask(nHeaderId) := vUsageMask;
9231 END IF;
9232
9233 nDebug := 8000102;
9234
9235 --Expression generation
9236
9237 IF(nRuleType IN (RULE_TYPE_TEMPLATE, RULE_TYPE_EXPRESSION))THEN
9238
9239 FOR i IN expressionStart..expressionEnd LOOP
9240 IF(v_tExprParentId(i) IS NULL)THEN
9241
9242 --Because of the ordering by expr_parent_id, all the expression tree roots will be at the end
9243 --after all their children. As soon as we hit the first of them we can start generating.
9244 --The construction of children lookup arrays has been moved directly after reading the
9245 --expression tree.
9246
9247 --Bugs #5160714, #5184017. Reset optimization and other parameters per rule. It is not enough
9248 --to do it once after for each rule record because rule text may consist of several rules.
9249 --These parameter are not used for other rule types.
9250
9251 optimizeChain := OPTIMIZATION_UNKNOWN;
9252 optimizeContribute := OPTIMIZATION_UNKNOWN;
9253 jAntecedentRoot := NULL;
9254 jConsequentRoot := NULL;
9255 RuleTemplateType := RULE_TYPE_UNKNOWN;
9256 numericLHS := 0;
9257 generateCompare := 0;
9258
9259 returnStringArray := GENERATE_EXPRESSION(i, returnListType);
9260 END IF;
9261 END LOOP;
9262 ELSIF(nRuleType = RULE_TYPE_COMPAT_TABLE)THEN
9263
9264 GENERATE_COMPATIBILITY_TABLE;
9265 ELSIF(nRuleType = RULE_TYPE_DESIGNCHART_RULE)THEN
9266
9267 GENERATE_DESIGNCHART_RULE;
9268 END IF; --End expression and rule generation
9269 END IF; --Not a rule folder or functional companion
9270
9271 --This block handles the exceptions during a rule generation. Every such exception
9272 --will stop generation only for the particular rule if not re-raised here.
9273
9274 EXCEPTION
9275 WHEN CZ_R_UNKNOWN_RULE_TYPE THEN
9276 --'Unknown rule type, rule ''%RULENAME'' ignored'
9277 REPORT(CZ_UTILS.GET_TEXT('CZ_R_UNKNOWN_RULE_TYPE', 'RULENAME', RULE_NAME), 1);
9278 PACK;
9279 WHEN CZ_R_INVALID_RULE THEN
9280 --'Rule ''%RULENAME'' cannot be generated because it relates an incorrect combination of components. Rule ignored.'
9281 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INVALID_RULE', 'RULENAME', RULE_NAME), 1);
9282 PACK;
9283 WHEN CZ_R_UNASSIGNABLE_RULE THEN
9284 --'Rule ''%RULENAME'' cannot be generated because the node ''%NODENAME'' is a descendant of the multiply
9285 -- instantiable component ''%COMPONENT'' inside the connected model ''%CONNECTOR'', and therefore cannot
9286 -- participate in rules. Rule ignored.'
9287 REPORT(CZ_UTILS.GET_TEXT('CZ_R_UNASSIGNABLE_RULE', 'NODENAME', localString, 'COMPONENT', glName(auxIndex), 'CONNECTOR', glName(auxCount), 'RULENAME', RULE_NAME), 1);
9288 PACK;
9289 WHEN CZ_R_OPTIONAL_INSIDE THEN
9290 --'Rule ''%RULENAME'' cannot be generated because the node ''%NODENAME'' is a descendant of the optional
9291 -- component ''%COMPONENT'' inside the connected model ''%CONNECTOR'', and therefore cannot participate
9292 -- in rules. Rule ignored.'
9293 REPORT(CZ_UTILS.GET_TEXT('CZ_R_OPTIONAL_INSIDE', 'NODENAME', localString, 'COMPONENT', glName(auxIndex), 'CONNECTOR', glName(auxCount), 'RULENAME', RULE_NAME), 1);
9294 PACK;
9295 WHEN CZ_R_OPTIONAL_ASIDE THEN
9296 --'Rule ''%RULENAME'' cannot be generated because it relates the multiply instantiable component ''%COMPONENT1''
9297 -- with the optional component ''%COMPONENT2''. Rule ignored.'
9298 REPORT(CZ_UTILS.GET_TEXT('CZ_R_OPTIONAL_ASIDE', 'COMPONENT1', glName(auxIndex), 'COMPONENT2', glName(auxCount), 'RULENAME', RULE_NAME), 1);
9299 PACK;
9300 WHEN CZ_R_CONNECTOR_ASIDE THEN
9301 --'Rule ''%RULENAME'' cannot be generated because it relates the multiply instantiable component ''%COMPONENT''
9302 -- with the connected model ''%CONNECTOR''. Rule ignored.'
9303 REPORT(CZ_UTILS.GET_TEXT('CZ_R_CONNECTOR_ASIDE', 'COMPONENT', glName(auxIndex), 'CONNECTOR', glName(auxCount), 'RULENAME', RULE_NAME), 1);
9304 PACK;
9305 WHEN CZ_R_CONFLICTING_NODES THEN
9306 --'Logic cannot be generated for Rule ''%RULENAME''. This is because the rule participants are descendants of
9307 -- Components ''%COMPONENT1'' and ''%COMPONENT2'' that can be instantiated multiple times. Rule ignored.'
9308 REPORT(CZ_UTILS.GET_TEXT('CZ_R_CONFLICTING_NODES', 'COMPONENT1', glName(auxIndex), 'COMPONENT2', glName(auxCount), 'RULENAME', RULE_NAME), 1);
9309 PACK;
9310 WHEN CZ_R_INCORRECT_NODE_LEVEL THEN
9311 --'Rule ''%RULENAME'' cannot be generated because it relates the multiply instantiable component ''%COMPONENT1'' with the component ''%COMPONENT2''.
9312 -- Rule ignored.'
9313 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCORRECT_NODE_LEVEL', 'COMPONENT1', glName(auxIndex), 'COMPONENT2', glName(auxCount), 'RULENAME', RULE_NAME), 1);
9314 PACK;
9315 WHEN CZ_R_ACROSS_TRACKABLE THEN
9316 --'Logic cannot be generated for rule ''%RULENAME'' because it relates a trackable instantiable Model with
9317 -- non-trackable items inside the Container Model ''%PROJECTNAME''. Rule ignored.'
9318 REPORT(CZ_UTILS.GET_TEXT('CZ_R_ACROSS_TRACKABLE', 'PROJECTNAME', rootProjectName, 'RULENAME', RULE_NAME), 1);
9319 PACK;
9320 WHEN CZ_R_CONNECTOR_RULE THEN
9321 --'Rule ''%RULENAME'' in the Model ''%MODELNAME'' is invalid. Connectors cannot participate in rules.'
9322 REPORT(CZ_UTILS.GET_TEXT('CZ_R_CONNECTOR_RULE', 'MODELNAME', thisProjectName, 'RULENAME', RULE_NAME), 1);
9323 PACK;
9324 WHEN CZ_R_INVALID_LOGIC_RULE THEN
9325 --'Invalid logic rule, rule ''%RULENAME'' ignored'
9326 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INVALID_LOGIC_RULE', 'RULENAME', RULE_NAME), 1);
9327 PACK;
9328 WHEN CZ_R_INCOMPLETE_LOGIC_RULE THEN
9329 --'Incomplete logic rule, rule ''%RULENAME'' ignored'
9330 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCOMPLETE_LOGIC_RULE', 'RULENAME', RULE_NAME), 1);
9331 PACK;
9332 WHEN CZ_R_LOGIC_RULE_WRONG_FEAT THEN
9333 --'Incorrect feature type in logic rule, feature ''%FEATNAME'', rule ''%RULENAME'' ignored'
9334 REPORT(CZ_UTILS.GET_TEXT('CZ_R_LOGIC_RULE_WRONG_FEAT', 'FEATNAME', localString, 'RULENAME', RULE_NAME), 1);
9335 PACK;
9336 WHEN CZ_R_NUMERIC_RULE_WRONG_FEAT THEN
9337 --'Incorrect feature type in numeric rule, feature ''%FEATNAME'', rule ''%RULENAME'' ignored'
9338 REPORT(CZ_UTILS.GET_TEXT('CZ_R_NUMERIC_RULE_WRONG_FEAT', 'FEATNAME', localString, 'RULENAME', RULE_NAME), 1);
9339 PACK;
9340 WHEN CZ_R_INCORRECT_FEATURE_TYPE THEN
9341 --'Text features are not allowed to participate in rules, feature ''%FEATNAME'', rule ''%RULENAME'' ignored.'
9342 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCORRECT_FEATURE_TYPE', 'FEATNAME', localString, 'RULENAME', RULE_NAME), 1);
9343 PACK;
9344 WHEN CZ_R_INVALID_NUMERIC_RULE THEN
9345 --'Invalid numeric rule, rule ''%RULENAME'' ignored'
9346 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INVALID_NUMERIC_RULE', 'RULENAME', RULE_NAME), 1);
9347 PACK;
9348 WHEN CZ_R_INCORRECT_NUMERIC_RHS THEN
9349 --'The node ''%NODENAME'' in the Model ''%MODELNAME'' is a(n) ''%NODETYPE''. This type of node cannot be
9350 -- a participant on the B side of a Numeric rule. Rule ''%RULENAME'' ignored.'
9351 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCORRECT_NUMERIC_RHS', 'NODENAME', localString, 'MODELNAME', thisProjectName, 'NODETYPE', errorMessage, 'RULENAME', RULE_NAME), 1);
9352 PACK;
9353 WHEN CZ_R_INCOMPATIBLE_SYSPROP THEN
9354 --'The Property ''%PROPERTYNAME'' is invalid for the node ''%NODENAME''. Rule ''%RULENAME'' in Model ''%MODELNAME'' ignored.'
9355 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCOMPATIBLE_SYSPROP', 'PROPERTYNAME', localString, 'NODENAME', glName(auxIndex), 'MODELNAME', thisProjectName, 'RULENAME', RULE_NAME), 1);
9356 PACK;
9357 WHEN CZ_R_INVALID_COMPARISON_RULE THEN
9358 --'Invalid comparison rule, rule ''%RULENAME'' ignored'
9359 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INVALID_COMPARISON_RULE', 'RULENAME', RULE_NAME), 1);
9360 PACK;
9361 WHEN CZ_R_INVALID_NUMERIC_PART THEN
9362 --'Invalid numeric part, rule ''%RULENAME'' ignored'
9363 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INVALID_NUMERIC_PART', 'RULENAME', RULE_NAME), 1);
9364 PACK;
9365 WHEN CZ_R_INCOMPLETE_NUMERIC_RULE THEN
9366 --'Incomplete numeric rule, rule ''%RULENAME'' ignored'
9367 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCOMPLETE_NUMERIC_RULE', 'RULENAME', RULE_NAME), 1);
9368 PACK;
9369 WHEN CZ_R_INVALID_NUMRULE_NODE THEN
9370 --'Invalid numeric rule node, rule ''%RULENAME'' ignored'
9371 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INVALID_NUMRULE_NODE', 'RULENAME', RULE_NAME), 1);
9372 PACK;
9373 WHEN CZ_R_INVALID_NUM_SIMPLE_EXPR THEN
9374 --'The left-hand side expression must have a root rounding operator, rule ''%RULENAME'' ignored'
9375 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INVALID_NUM_SIMPLE_EXPR', 'RULENAME', RULE_NAME), 1);
9376 PACK;
9377 WHEN CZ_E_UNKNOWN_EXPR_TYPE THEN
9378 --'Unknown expression type, rule ''%RULENAME'' ignored'
9379 REPORT(CZ_UTILS.GET_TEXT('CZ_E_UNKNOWN_EXPR_TYPE', 'RULENAME', RULE_NAME), 1);
9380 PACK;
9381 WHEN CZ_E_WRONG_ARITHMETIC_OPER THEN
9382 --'Incorrect arithmetic operator, rule ''%RULENAME'' ignored'
9383 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_ARITHMETIC_OPER', 'RULENAME', RULE_NAME), 1);
9384 PACK;
9385 WHEN CZ_E_WRONG_COMPARISON_OPER THEN
9386 --'Incorrect comparison operator, rule ''%RULENAME'' ignored'
9387 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_COMPARISON_OPER', 'RULENAME', RULE_NAME), 1);
9388 PACK;
9389 WHEN CZ_E_WRONG_ROUND_OPERATOR THEN
9390 --'Incorrect ROUND operator, rule ''%RULENAME'' ignored'
9391 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_ROUND_OPERATOR', 'RULENAME', RULE_NAME), 1);
9392 PACK;
9393 WHEN CZ_E_WRONG_ANDOR_OPERATOR THEN
9394 --'Incorrect AND/OR operator, rule ''%RULENAME'' ignored'
9395 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_ANDOR_OPERATOR', 'RULENAME', RULE_NAME), 1);
9396 PACK;
9397 WHEN CZ_E_WRONG_NOT_OPERATOR THEN
9398 --'Incorrect NOT operator, rule ''%RULENAME'' ignored'
9399 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_NOT_OPERATOR', 'RULENAME', RULE_NAME), 1);
9400 PACK;
9401 WHEN CZ_E_WRONG_NOTTRUE_OPERATOR THEN
9402 --'Incorrect NOTTRUE operator, rule ''%RULENAME'' ignored'
9403 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_NOTTRUE_OPERATOR', 'RULENAME', RULE_NAME), 1);
9404 PACK;
9405 WHEN CZ_E_WRONG_VAL_EXPRESSION THEN
9406 --'Incorrect VAL expression, rule ''%RULENAME'' ignored'
9407 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_VAL_EXPRESSION', 'RULENAME', RULE_NAME), 1);
9408 PACK;
9409 WHEN CZ_E_WRONG_VAL_EXPRESS_TYPE THEN
9410 --'Incorrect VAL expression type, rule ''%RULENAME'' ignored'
9411 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_VAL_EXPRESS_TYPE', 'RULENAME', RULE_NAME), 1);
9412 PACK;
9413 WHEN CZ_E_WRONG_MINMAX_OPERATOR THEN
9414 --'Incorrect MIN/MAX operator, rule ''%RULENAME'' ignored'
9415 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_MINMAX_OPERATOR', 'RULENAME', RULE_NAME), 1);
9416 PACK;
9417 WHEN CZ_E_WRONG_OF_OPERATOR THEN
9418 --'Incorrect OF operator, rule ''%RULENAME'' ignored'
9419 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_OF_OPERATOR', 'RULENAME', RULE_NAME), 1);
9420 PACK;
9421 WHEN CZ_E_WRONG_DOT_OPERATOR THEN
9422 --'Incorrect DOT operator, rule ''%RULENAME'' ignored'
9423 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_DOT_OPERATOR', 'RULENAME', RULE_NAME), 1);
9424 PACK;
9425 WHEN CZ_E_DOT_TYPE_MISMATCH THEN
9426 --'DOT type mismatch, rule ''%RULENAME'' ignored'
9427 REPORT(CZ_UTILS.GET_TEXT('CZ_E_DOT_TYPE_MISMATCH', 'RULENAME', RULE_NAME), 1);
9428 PACK;
9429 WHEN CZ_E_BAD_PROPERTY_TYPE THEN
9430 --'Bad property type, rule ''%RULENAME'' ignored'
9431 REPORT(CZ_UTILS.GET_TEXT('CZ_E_BAD_PROPERTY_TYPE', 'RULENAME', RULE_NAME), 1);
9432 PACK;
9433 WHEN CZ_E_NO_SUCH_PROPERTY THEN
9434 --'No such property, rule ''%RULENAME'' ignored'
9435 REPORT(CZ_UTILS.GET_TEXT('CZ_E_NO_SUCH_PROPERTY', 'RULENAME', RULE_NAME), 1);
9436 PACK;
9437 WHEN CZ_E_NULL_PROPERTY_VALUE THEN
9438 --'Null property value, rule ''%RULENAME'' ignored'
9439 REPORT(CZ_UTILS.GET_TEXT('CZ_E_NULL_PROPERTY_VALUE', 'RULENAME', RULE_NAME), 1);
9440 PACK;
9441 WHEN CZ_E_INCORRECT_PROPERTY THEN
9442 --'Unable to identify property value, rule ''%RULENAME'' ignored'
9443 REPORT(CZ_UTILS.GET_TEXT('CZ_E_INCORRECT_PROPERTY', 'RULENAME', RULE_NAME), 1);
9444 PACK;
9445 WHEN CZ_E_UNKNOWN_OPERATOR_TYPE THEN
9446 --'Unknown operator type, type %OPERTYPE, rule ''%RULENAME'' ignored'
9447 REPORT(CZ_UTILS.GET_TEXT('CZ_E_UNKNOWN_OPERATOR_TYPE', 'OPERTYPE', TO_CHAR(nParam), 'RULENAME', RULE_NAME), 1);
9448 PACK;
9449 WHEN CZ_E_INVALID_OPERAND_TYPE THEN
9450 --'Invalid operand type, operator ''%OPERNAME'', rule ''%RULENAME'' ignored'
9451 REPORT(CZ_UTILS.GET_TEXT('CZ_E_INVALID_OPERAND_TYPE', 'OPERNAME', LTRIM(RTRIM(OperatorLiterals(v_tExprSubtype(nParam)))), 'RULENAME', RULE_NAME), 1);
9452 PACK;
9453 WHEN CZ_E_MATH_PARAMETERS THEN
9454 --'Incorrect number of parameters to mathematical function %FUNCTION, rule ''%RULENAME'' ignored'
9455 REPORT(CZ_UTILS.GET_TEXT('CZ_E_MATH_PARAMETERS', 'RULENAME', RULE_NAME, 'FUNCTION', LTRIM(RTRIM(OperatorLiterals(nParam)))), 1);
9456 PACK;
9457 WHEN CZ_E_INCORRECT_POWER THEN
9458 --'Exponent value of a POW function could not be resolved to a constant integer, rule ''%RULENAME'' ignored'
9459 REPORT(CZ_UTILS.GET_TEXT('CZ_E_INCORRECT_POWER', 'RULENAME', RULE_NAME), 1);
9460 PACK;
9461 WHEN CZ_R_UNABLE_TO_CREATE_TABLE THEN
9462 --'Unable to create a temporary table for property-based compatibility rule, rule ''%RULENAME'' ignored, error: %ERRORTEXT'
9463 REPORT(CZ_UTILS.GET_TEXT('CZ_R_UNABLE_TO_CREATE_TABLE', 'RULENAME', RULE_NAME, 'ERRORTEXT', errorMessage), 1);
9464 PACK;
9465 WHEN CZ_R_WRONG_COMPAT_EXPRESSION THEN
9466 --'Incorrect compatibility expression, rule ''%RULENAME'' ignored'
9467 REPORT(CZ_UTILS.GET_TEXT('CZ_R_WRONG_COMPAT_EXPRESSION', 'RULENAME', RULE_NAME), 1);
9468 PACK;
9469 WHEN CZ_E_WRONG_OPER_IN_COMPAT THEN
9470 --'Incorrect operator in compatibility rule, rule ''%RULENAME'' ignored'
9471 REPORT(CZ_UTILS.GET_TEXT('CZ_E_WRONG_OPER_IN_COMPAT', 'RULENAME', RULE_NAME), 1);
9472 PACK;
9473 WHEN CZ_E_UKNOWN_OPER_IN_COMPAT THEN
9474 --'Unknown operator in compatibility rule, rule ''%RULENAME'' ignored'
9475 REPORT(CZ_UTILS.GET_TEXT('CZ_E_UKNOWN_OPER_IN_COMPAT', 'RULENAME', RULE_NAME), 1);
9476 PACK;
9477 WHEN CZ_R_COMPAT_NO_COMBINATIONS THEN
9478 --'No valid combinations, rule ''%RULENAME'' ignored'
9479 REPORT(CZ_UTILS.GET_TEXT('CZ_R_COMPAT_NO_COMBINATIONS', 'RULENAME', RULE_NAME), 1);
9480 PACK;
9481 WHEN CZ_R_WRONG_EXPRESSION_NODE THEN
9482 --'Incorrect node in expression, rule ''%RULENAME'' ignored'
9483 REPORT(CZ_UTILS.GET_TEXT('CZ_R_WRONG_EXPRESSION_NODE', 'RULENAME', RULE_NAME), 1);
9484 PACK;
9485 WHEN CZ_R_NO_DEFINING_SELECTION THEN
9486 --'No selection made between primary and defining feature in design chart rule, rule ''%RULENAME'' ignored'
9487 REPORT(CZ_UTILS.GET_TEXT('CZ_R_NO_DEFINING_SELECTION', 'RULENAME', RULE_NAME), 1);
9488 PACK;
9489 WHEN CZ_R_NO_PRIMARY_FEATURE THEN
9490 --'No primary feature in design chart rule, rule ''%RULENAME'' ignored'
9491 REPORT(CZ_UTILS.GET_TEXT('CZ_R_NO_PRIMARY_FEATURE', 'RULENAME', RULE_NAME), 1);
9492 PACK;
9493 WHEN CZ_R_DELETED_OPTION THEN
9494 --'The Model structure has changed and the Design Chart rule ''%RULENAME'' now contains deleted node ''%NODENAME''.
9495 -- The rule will be ignored.'
9496 REPORT(CZ_UTILS.GET_TEXT('CZ_R_DELETED_OPTION', 'RULENAME', RULE_NAME, 'NODENAME', errorMessage), 1);
9497 PACK;
9498 WHEN CZ_R_WRONG_DESIGNCHART_RULE THEN
9499 --'No one-to-one correspondence between options of primary and defining feature in design chart rule, rule ''%RULENAME'' ignored'
9500 REPORT(CZ_UTILS.GET_TEXT('CZ_R_WRONG_DESIGNCHART_RULE', 'RULENAME', RULE_NAME), 1);
9501 PACK;
9502 WHEN CZ_R_DUPLICATE_COMBINATION THEN
9503 --'Not unique combination of defining feature options for a primary option in design chart rule, rule ''%RULENAME'' ignored'
9504 REPORT(CZ_UTILS.GET_TEXT('CZ_R_DUPLICATE_COMBINATION', 'RULENAME', RULE_NAME), 1);
9505 PACK;
9506 WHEN CZ_R_INCOMPLETE_DES_CHART THEN
9507 --'Incorrect number of compatibility selections made for the option ''%OPTIONNAME'' of the Primary Feature ''%FEATURENAME''
9508 -- in Design Chart ''%RULENAME''. Rule ignored.'
9509 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCOMPLETE_DES_CHART', 'OPTIONNAME', glName(auxIndex), 'FEATURENAME', glName(auxCount), 'RULENAME', RULE_NAME), 1);
9510 PACK;
9511 WHEN CZ_R_EMPTY_COMPAT_RULE THEN
9512 --'Empty compatibility rule, rule ''%RULENAME'' ignored'
9513 REPORT(CZ_UTILS.GET_TEXT('CZ_R_EMPTY_COMPAT_RULE', 'RULENAME', RULE_NAME), 1);
9514 PACK;
9515 WHEN CZ_R_COMPAT_SINGLE_FEATURE THEN
9516 --'Compatibility rule must have at least two participating features, rule ''%RULENAME'' ignored'
9517 REPORT(CZ_UTILS.GET_TEXT('CZ_R_COMPAT_SINGLE_FEATURE', 'RULENAME', RULE_NAME), 1);
9518 PACK;
9519 WHEN CZ_R_COMPAT_RULE_NO_PROPERTY THEN
9520 --'Incomplete compatibility rule, no property defined for feature ''%FEATNAME'', rule ''%RULENAME'' ignored'
9521 REPORT(CZ_UTILS.GET_TEXT('CZ_R_COMPAT_RULE_NO_PROPERTY', 'FEATNAME', glName(glIndexByPsNodeId(v_tExprPsNodeId(nParam))), 'RULENAME', RULE_NAME), 1);
9522 PACK;
9523 WHEN CZ_R_OPTION_NO_PROPERTY THEN
9524 --'Property value for ''%PROPERTYNAME'' is not defined for item ''%ITEMNAME'' with parent ''%PARENTNAME'' in model ''%MODELNAME''. Rule ''%RULENAME'' ignored.'
9525 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);
9526 PACK;
9527 WHEN CZ_R_LONG_PROPERTY_VALUE THEN
9528 --'Value of the Property ''%PROPERTYNAME'' is too long for item ''%ITEMNAME'' with parent ''%PARENTNAME'' in model ''%MODELNAME''. Rule ''%RULENAME'' ignored.'
9529 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);
9530 PACK;
9531 WHEN CZ_R_INCORRECT_DATA_TYPE THEN
9532 --'Incorrect data: integer or decimal property ''%PROPERTYNAME'' has a text value of ''%VALUE''. Rule ''%RULENAME'' in model ''%MODELNAME'' ignored.'
9533 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCORRECT_DATA_TYPE', 'PROPERTYNAME', errorMessage, 'VALUE', localString, 'MODELNAME', glName(glIndexByPsNodeId(inProjectId)), 'RULENAME', RULE_NAME), 1);
9534 PACK;
9535 WHEN CZ_R_INCORRECT_NUMERICLHS THEN
9536 --'''%PROPERTYNAME'' is invalid in the Numeric rule ''%RULENAME'' in Model ''%MODELNAME''. Text and Boolean Properties
9537 -- cannot be participants on the left-hand side of a Numeric rule. Rule ignored.'
9538 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCORRECT_NUMERICLHS', 'PROPERTYNAME', errorMessage, 'MODELNAME', glName(glIndexByPsNodeId(inProjectId)), 'RULENAME', RULE_NAME), 1);
9539 PACK;
9540 WHEN CZ_R_PROPERTY_NOT_ALLOWED THEN
9541 --'The expression contained a Text property which is only allowed in a comparison expression. A Text property is not
9542 -- allowed in the context of your expression. Rule ''%RULENAME'' in Model ''%MODELNAME'' ignored.'
9543 REPORT(CZ_UTILS.GET_TEXT('CZ_R_PROPERTY_NOT_ALLOWED', 'MODELNAME', glName(glIndexByPsNodeId(inProjectId)), 'RULENAME', RULE_NAME), 1);
9544 PACK;
9545 WHEN CZ_R_VIRTUAL_COMPONENT THEN
9546 --'The system property ''%PROPERTYNAME'' is not allowed because ''%NODENAME'' is required. Refer to Oracle Configurator
9547 -- Developer documentation for details. Rule ''%RULENAME'' ignored.'
9548 REPORT(CZ_UTILS.GET_TEXT('CZ_R_VIRTUAL_COMPONENT', 'PROPERTYNAME', localString, 'NODENAME', glName(nParam), 'RULENAME', RULE_NAME), 1);
9549 PACK;
9550 WHEN CZ_R_WRONG_COMPAT_TABLE THEN
9551 --'Incorrect explicit compatibility table, rule ''%RULENAME'' ignored'
9552 REPORT(CZ_UTILS.GET_TEXT('CZ_R_WRONG_COMPAT_TABLE', 'RULENAME', RULE_NAME), 1);
9553 PACK;
9554 WHEN CZ_R_NO_PARTICIPANTS THEN
9555 --'Incomplete rule - no participants, rule ''%RULENAME'' ignored'
9556 REPORT(CZ_UTILS.GET_TEXT('CZ_R_NO_PARTICIPANTS', 'RULENAME', RULE_NAME), 1);
9557 PACK;
9558 WHEN CZ_R_NO_COMPONENT_ID THEN
9559 --'No ps_node_id defined for none of the rule participants, rule ''%RULENAME'' ignored'
9560 REPORT(CZ_UTILS.GET_TEXT('CZ_R_NO_COMPONENT_ID', 'RULENAME', RULE_NAME), 1);
9561 PACK;
9562 WHEN CZ_R_RULE_WRONG_EXPRESSION THEN
9563 --'Invalid expression specified, rule ''%RULENAME'' ignored'
9564 REPORT(CZ_UTILS.GET_TEXT('CZ_R_RULE_WRONG_EXPRESSION', 'RULENAME', RULE_NAME), 1);
9565 PACK;
9566 WHEN CZ_R_WRONG_EFFECTIVITY_SET THEN
9567 --'Invalid effectivity set assosiated with rule ''%RULENAME'', rule ignored'
9568 REPORT(CZ_UTILS.GET_TEXT('CZ_R_WRONG_EFFECTIVITY_SET', 'RULENAME', RULE_NAME), 1);
9569 PACK;
9570 WHEN CZ_R_LITERAL_NO_VALUE THEN
9571 --'No literal value specified in rule ''%RULENAME'', rule ignored'
9572 REPORT(CZ_UTILS.GET_TEXT('CZ_R_LITERAL_NO_VALUE', 'RULENAME', RULE_NAME), 1);
9573 PACK;
9574 WHEN CZ_R_INCORRECT_NODE_ID THEN
9575 --'Incomplete or invalid data in rule ''%RULENAME'', rule ignored'
9576 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCORRECT_NODE_ID', 'RULENAME', RULE_NAME), 1);
9577 PACK;
9578 WHEN CZ_R_FEATURE_NO_PROPERTY THEN
9579 --'Invalid property or no property specified in rule ''%RULENAME'', rule ignored'
9580 REPORT(CZ_UTILS.GET_TEXT('CZ_R_FEATURE_NO_PROPERTY', 'RULENAME', RULE_NAME), 1);
9581 PACK;
9582 WHEN CZ_R_INCORRECT_REFERENCE THEN
9583 --'The reference %PATH is invalid. At least one node does not exist in the Model or is not effective when the rule is effective.
9584 -- Rule ''%RULENAME'' ignored.'
9585 REPORT(CZ_UTILS.GET_TEXT('CZ_R_INCORRECT_REFERENCE', 'PATH', localString, 'RULENAME', RULE_NAME), 1);
9586 PACK;
9587 WHEN CZ_R_AMBIGUOUS_REFERENCE THEN
9588 --'Unable to resolve Model node reference %PATH because it is ambiguous. Rule ''%RULENAME'' ignored.'
9589 REPORT(CZ_UTILS.GET_TEXT('CZ_R_AMBIGUOUS_REFERENCE', 'PATH', localString, 'RULENAME', RULE_NAME), 1);
9590 PACK;
9591 WHEN CZ_E_NO_EXPECTED_CHILDREN THEN
9592 --'Node ''%NODENAME'' has no children, rule ''%RULENAME'' ignored'
9593 REPORT(CZ_UTILS.GET_TEXT('CZ_E_NO_EXPECTED_CHILDREN', 'NODENAME', localString, 'RULENAME', RULE_NAME), 1);
9594 PACK;
9595 WHEN CZ_E_NO_OPTIONAL_CHILDREN THEN
9596 --'All children of the BOM node ''%NODENAME'' are required when parent is selected, no optional children, rule ''%RULENAME'' ignored'
9597 REPORT(CZ_UTILS.GET_TEXT('CZ_E_NO_OPTIONAL_CHILDREN', 'NODENAME', localString, 'RULENAME', RULE_NAME), 1);
9598 PACK;
9599 WHEN CZ_R_TRACKABLE_ANCESTOR THEN
9600 --'BOM item ''%ITEMNAME'' cannot participate in the Numeric rule ''%RULENAME'' because it contains other trackable BOM items.'
9601 REPORT(CZ_UTILS.GET_TEXT('CZ_R_TRACKABLE_ANCESTOR', 'ITEMNAME', glName(nParam), 'RULENAME', RULE_NAME), 1);
9602 PACK;
9603 WHEN CZ_R_AGAINST_TRACKABLE THEN
9604 --'Numeric rule ''%RULENAME'' is invalid. In a Container Model, a Numeric rule cannot contribute to or consume
9605 -- from how many instances of a trackable Model are allowed at runtime.'
9606 REPORT(CZ_UTILS.GET_TEXT('CZ_R_AGAINST_TRACKABLE', 'RULENAME', RULE_NAME), 1);
9607 PACK;
9608 --'Only nontranslatable System Properties are allowed in the WHERE clause of a COMPATIBLE or FORALL operator.
9609 -- The System Property ''%PROPERTYNAME'' can be translated, therefore it is invalid in this context. Rule ''%RULENAME''
9610 -- in the Model ''%MODELNAME'' will be ignored.'
9611 WHEN CZ_E_DESCRIPTION_IN_WHERE THEN
9612 REPORT(CZ_UTILS.GET_TEXT('CZ_E_DESCRIPTION_IN_WHERE', 'PROPERTYNAME', errorMessage,'MODELNAME', thisProjectName, 'RULENAME', RULE_NAME), 1);
9613 PACK;
9614 --'Only static System Properties are allowed in the WHERE clause of a COMPATIBLE or FORALL operator. The value of the
9615 -- System Property ''%PROPERTYNAME'' can change at runtime, therefore it is invalid in this context. Rule ''%RULENAME''
9616 -- in the Model ''%MODELNAME'' will be ignored.'
9617 WHEN CZ_E_PROPERTY_NOT_STATIC THEN
9618 REPORT(CZ_UTILS.GET_TEXT('CZ_E_PROPERTY_NOT_STATIC', 'PROPERTYNAME', errorMessage,'MODELNAME', thisProjectName, 'RULENAME', RULE_NAME), 1);
9619 PACK;
9620 WHEN CZ_R_TEMPLATE_UNKNOWN OR CZ_R_EMPTY_PARAMETER_SCOPE OR CZ_R_PARAMETER_NOT_FOUND OR
9621 CZ_R_TYPE_NO_PROPERTY OR CZ_R_NO_SIGNATURE_ID THEN
9622 --'Unable to generate rule ''%RULENAME'', internal data error.'
9623 REPORT(CZ_UTILS.GET_TEXT('CZ_G_INTERNAL_RULE_ERROR', 'RULENAME', RULE_NAME), 1);
9624 PACK;
9625 WHEN CZ_G_INVALID_RULE_EXPLOSION THEN
9626 --This is fatal: model_ref_expl_id of one of the participants references an explosion table
9627 --other than the current model table
9628 errorMessage := RULE_NAME;
9629 IF(StopOnFatalRuleError = 1)THEN
9630 IF(c_rules%ISOPEN)THEN CLOSE c_rules; END IF;
9631 RAISE;
9632 ELSE
9633 --'Unable to generate rule ''%RULENAME'', internal data error.'
9634 REPORT(CZ_UTILS.GET_TEXT('CZ_G_INTERNAL_RULE_ERROR', 'RULENAME', errorMessage), 1);
9635 PACK;
9636 END IF;
9637 WHEN CZ_R_UNABLE_TO_CREATE_HEADER THEN
9638
9639 --This is supposed to be a definitely fatal error, so raise the exception.
9640
9641 IF(c_rules%ISOPEN)THEN CLOSE c_rules; END IF;
9642 RAISE;
9643 WHEN CZ_LCE_CONTINUE THEN
9644 --This exception is used to immediately move to the next loop, not an error.
9645 NULL;
9646 WHEN OTHERS THEN
9647 IF(nDebug >= 40 AND nDebug <= 54)THEN
9648 errorMessage := RULE_NAME;
9649 ELSIF(SUBSTR(TO_CHAR(nDebug), 1, 1) = '8')THEN
9650 errorMessage := TO_CHAR(nRuleId);
9651 END IF;
9652
9653 --When the first data corruption-type error for a rule is encountered, logic gen stops.
9654 --However, it may be convenient for debugging purposes to be able to report all of such
9655 --rules. So, check the db setting here.
9656
9657 IF(StopOnFatalRuleError = 1)THEN
9658 IF(c_rules%ISOPEN)THEN CLOSE c_rules; END IF;
9659 RAISE;
9660 ELSE
9661 --'Unable to generate rule ''%RULENAME'', internal error %ERRORTEXT'
9662 REPORT(CZ_UTILS.GET_TEXT('CZ_G_GENERAL_RULE_ERROR', 'RULENAME', RULE_NAME, 'ERRORTEXT', SQLERRM), 1);
9663 PACK;
9664 END IF;
9665 END;
9666 END LOOP;
9667 CLOSE c_rules;
9668
9669 --Now generate the INC relations into the root rule file for the non-virtual components
9670 --that have rules against their max.
9671
9672 IF(v_MaxRuleExists.COUNT > 0)THEN
9673 IF(v_tIsHeaderGenerated.EXISTS(thisComponentExplId))THEN
9674
9675 --Use this header to generate the rule into
9676
9677 nHeaderId := v_tIsHeaderGenerated(thisComponentExplId);
9678
9679 ELSE
9680
9681 nHeaderId := next_lce_header_id;
9682
9683 BEGIN
9684
9685 --Insert the rule net logic header record into the table
9686
9687 INSERT INTO cz_lce_headers
9688 (lce_header_id, gen_version, gen_header, component_id, net_type,
9689 devl_project_id, model_ref_expl_id, nbr_required_expls, deleted_flag)
9690 VALUES
9691 (nHeaderId, VersionString, GenHeader, inComponentId, LOGIC_NET_TYPE_MANDATORY,
9692 thisProjectId, thisComponentExplId, 1, FLAG_PENDING);
9693
9694 INSERT INTO cz_lce_load_specs
9695 (attachment_expl_id, lce_header_id, required_expl_id, attachment_comp_id,
9696 model_id, net_type, deleted_flag)
9697 VALUES
9698 (thisComponentExplId, nHeaderId, thisComponentExplId, inComponentId,
9699 thisProjectId, LOGIC_NET_TYPE_MANDATORY, FLAG_PENDING);
9700
9701 EXCEPTION
9702 WHEN OTHERS THEN
9703 errorMessage := SQLERRM;
9704 RAISE CZ_R_UNABLE_TO_CREATE_HEADER;
9705 END;
9706
9707 NewHeaders(counterNewHeaders) := nHeaderId;
9708 NewHeadersComponents(counterNewHeaders) := inComponentId;
9709 NewHeadersExplosions(counterNewHeaders) := thisComponentExplId;
9710 counterNewHeaders := counterNewHeaders + 1;
9711
9712 v_tIsHeaderGenerated(thisComponentExplId) := nHeaderId;
9713 v_tSequenceNbr(nHeaderId) := 1;
9714 v_tLogicNetType(nHeaderId) := LOGIC_NET_TYPE_MANDATORY;
9715 nNewLogicFileFlag := 1;
9716
9717 END IF;
9718
9719 --If the logic file has changed then we need to flush off the buffer
9720
9721 IF(nHeaderId <> nPreviousHeaderId)THEN
9722
9723 IF(vLogicText IS NOT NULL)THEN
9724 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
9725 (nPreviousHeaderId, v_tSequenceNbr(nPreviousHeaderId), vLogicText);
9726 vLogicText := NULL;
9727 v_tSequenceNbr(nPreviousHeaderId) := v_tSequenceNbr(nPreviousHeaderId) + 1;
9728 END IF;
9729
9730 END IF;
9731
9732 IF(nNewLogicFileFlag = 1)THEN
9733
9734 --This is a new logic file, put the header lines in
9735
9736 vLogicLine := 'CONTROL NOSPEC' || NewLine || 'VERSION 3 3' || NewLine || NewLine ||
9737 'REM -- Rules file for component: ' || TO_CHAR(inComponentId) ||
9738 ', explosion node: ' || TO_CHAR(thisComponentExplId) || NewLine || NewLine ||
9739 'EFF , , ' || NewLine || NewLine;
9740 PACK;
9741 END IF;
9742
9743 FOR i IN 1..v_NodeId.COUNT LOOP
9744 IF(v_MaxRuleExists.EXISTS(v_NodeId(i)) AND v_tVirtualFlag(i) = FLAG_NON_VIRTUAL AND
9745 v_tNodeDepth(i) > 0)THEN
9746
9747 --Use intermediate variable instead of using NVL because this is faster
9748
9749 IF(v_tReferringId(i) IS NOT NULL)THEN
9750 localString := TO_CHAR(glPersistentId(v_tReferringId(i)));
9751 ELSE
9752 localString := TO_CHAR(glPersistentId(v_tPsNodeId(i)));
9753 END IF;
9754
9755 vLogicLine := 'INC 1 P_' || localString || '_MAX round' || NewLine;
9756 PACK;
9757
9758 END IF;
9759 END LOOP;
9760
9761 END IF;
9762
9763 nDebug := 9;
9764
9765 --Flush off the buffer after rules generation
9766
9767 IF(vLogicText IS NOT NULL)THEN
9768 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
9769 (nHeaderId, v_tSequenceNbr(nHeaderId), vLogicText);
9770 vLogicText := NULL;
9771 v_tSequenceNbr(nHeaderId) := v_tSequenceNbr(nHeaderId) + 1;
9772 END IF;
9773
9774 FOR i IN 1..temp_tables.COUNT LOOP
9775 BEGIN
9776 EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || temp_tables(i);
9777 EXECUTE IMMEDIATE 'DROP TABLE ' || temp_tables(i);
9778 EXCEPTION
9779 WHEN OTHERS THEN
9780 IF(SQLCODE <> ORACLE_OBJECT_IN_USE)THEN RAISE; END IF;
9781 END;
9782 END LOOP;
9783
9784 IF(TwoPhaseCommit = 0)THEN COMMIT; END IF;
9785
9786 EXCEPTION
9787 WHEN OTHERS THEN
9788 FOR i IN 1..temp_tables.COUNT LOOP
9789 BEGIN
9790 EXECUTE IMMEDIATE 'TRUNCATE TABLE ' || temp_tables(i);
9791 EXECUTE IMMEDIATE 'DROP TABLE ' || temp_tables(i);
9792 EXCEPTION
9793 WHEN OTHERS THEN
9794 NULL;
9795 END;
9796 END LOOP;
9797 RAISE;
9798 END; --GENERATE_RULES
9799 ---------------------------------------------------------------------------------------
9800 BEGIN --GENERATE_COMPONENT_TREE - Product Structure Generation
9801
9802 --Generate next lce_header_id for this LCE file. This is the structure net for a model or
9803 --non-virtual component.
9804
9805 nDebug := 1110000;
9806
9807 IF(inParentLogicHeaderId IS NULL)THEN
9808
9809 --If this is the root model, read and store its name and type for later use.
9810
9811 BEGIN
9812
9813 SELECT name, model_type INTO thisProjectName, thisProjectType
9814 FROM cz_devl_projects
9815 WHERE devl_project_id = inComponentId;
9816 EXCEPTION
9817 WHEN OTHERS THEN
9818 nParam := inComponentId;
9819 RAISE CZ_S_NO_SUCH_PROJECT;
9820 END;
9821
9822 IF(inComponentId = inDevlProjectId)THEN
9823
9824 --Store the name and type of the root project for which the logic generation was
9825 --originally started.
9826
9827 rootProjectName := thisProjectName;
9828 rootProjectType := thisProjectType;
9829 ELSIF(thisProjectType = MODEL_TYPE_CONTAINER_MODEL AND rootProjectType = MODEL_TYPE_CONTAINER_MODEL)THEN
9830
9831 --Container cannot be referenced or connected to.
9832
9833 errorMessage := thisProjectName;
9834 RAISE CZ_S_CONTAINER_REFERENCE;
9835 END IF;
9836 END IF;
9837
9838 IF(NOT IsLogicGenerated.EXISTS(inComponentId))THEN
9839
9840 --Read the explosions table here. It will be extensively used in rule generation. For the
9841 --structure generation, there is really no need in this table, except that now we want to
9842 --put reasonable values into CZ_LCE_HEADERS.MODEL_REF_EXPL_ID even for structure files as
9843 --this column is being made not nullable in 18.
9844
9845 IF(inParentLogicHeaderId IS NULL)THEN
9846
9847 --If this is the root model, read the table and populate project's id and explosion id
9848 --variables, and hash tables.
9849
9850 SELECT model_ref_expl_id, parent_expl_node_id, node_depth,
9851 ps_node_type, virtual_flag, component_id, referring_node_id,
9852 child_model_expl_id, expl_node_type
9853 BULK COLLECT INTO v_NodeId, v_tParentId, v_tNodeDepth,
9854 v_tNodeType, v_tVirtualFlag, v_tPsNodeId, v_tReferringId,
9855 v_tChildModelExpl, v_tExplNodeType
9856 FROM cz_model_ref_expls
9857 WHERE model_id = inComponentId AND deleted_flag = FLAG_NOT_DELETED;
9858
9859 FOR i IN 1..v_NodeId.COUNT LOOP
9860
9861 nDebug := 1110010;
9862
9863 IF(v_tVirtualFlag(i) = FLAG_NON_VIRTUAL AND v_tExplNodeType(i) = EXPL_NODE_TYPE_MANDATORY)THEN
9864
9865 --This is introduced as a remedy to a well-known type of data corruption occured during
9866 --the development process. May be removed later on when the data become stable.
9867
9868 errorMessage := thisProjectName;
9869 RAISE CZ_G_INVALID_EXPLOSION_TYPE;
9870 END IF;
9871
9872 nDebug := 1110001;
9873
9874 --Add another indexing option - by model_ref_expl_id
9875
9876 v_IndexByNodeId(v_NodeId(i)) := i;
9877
9878 --Store the explosion id and the index of the root node - the project node itself.
9879
9880 IF(v_tNodeDepth(i) = 0)THEN
9881 thisComponentExplId := v_NodeId(i);
9882 thisRootExplIndex := i;
9883 END IF;
9884
9885 --Create the EXPL_NODE_TYPE(MODEL_REF_EXPL_ID) hash table. Other explosion columns
9886 --are currently indexed through v_IndexByNodeId. Using direct hash may provide for
9887 --some performance improvement.
9888
9889 v_TypeByExplId(v_NodeId(i)) := v_tExplNodeType(i);
9890
9891 --Build the MODEL_REF_EXPL_ID(COMPONENT_ID) hash table for all the components
9892 --inside this project (not inside referenced projects). All such components
9893 --have CHILD_MODEL_EXPL_ID null. We need this table to populate MODEL_REF_EXPL_ID
9894 --in CZ_LCE_HEADERS records for structure file of this component.
9895
9896 IF(v_tChildModelExpl(i) IS NULL)THEN
9897 v_NodeIdByComponent(v_tPsNodeId(i)) := v_NodeId(i);
9898 END IF;
9899 END LOOP;
9900 ELSE
9901
9902 nDebug := 1110002;
9903
9904 --This is a non-virtual component inside this project, so the value in the
9905 --hash table exists.
9906 --We do not have to populate thisRootExplIndex, because it is used only in
9907 --rule generation and this will not be called for a non-root component.
9908 --Have to populate the other two variables though as they are used here in
9909 --the structure generation.
9910
9911 thisComponentExplId := v_NodeIdByComponent(inComponentId);
9912 END IF;
9913
9914 thisProjectId := inProjectId;
9915
9916 --Generate next lce_header_id for this LCE file. This is the structure net for a model or
9917 --non-virtual component.
9918
9919 nStructureHeaderId := next_lce_header_id;
9920
9921 BEGIN
9922
9923 --Insert the structure logic header record into the table.
9924
9925 INSERT INTO cz_lce_headers
9926 (lce_header_id, gen_version, gen_header, component_id, net_type,
9927 devl_project_id, model_ref_expl_id, nbr_required_expls, deleted_flag)
9928 VALUES
9929 (nStructureHeaderId, VersionString, GenHeader, inComponentId, LOGIC_NET_TYPE_STRUCTURE,
9930 thisProjectId, thisComponentExplId, 1, FLAG_PENDING);
9931
9932 --Insert the structure load conditions record for this component.
9933
9934 INSERT INTO cz_lce_load_specs
9935 (attachment_expl_id, lce_header_id, required_expl_id, attachment_comp_id,
9936 model_id, net_type, deleted_flag)
9937 VALUES
9938 (thisComponentExplId, nStructureHeaderId, thisComponentExplId, inComponentId,
9939 thisProjectId, LOGIC_NET_TYPE_STRUCTURE, FLAG_PENDING);
9940
9941 EXCEPTION
9942 WHEN OTHERS THEN
9943 errorMessage := SQLERRM;
9944 RAISE CZ_S_UNABLE_TO_CREATE_HEADER;
9945 END;
9946
9947 NewHeaders(counterNewHeaders) := nStructureHeaderId;
9948 NewHeadersComponents(counterNewHeaders) := inComponentId;
9949 NewHeadersExplosions(counterNewHeaders) := thisComponentExplId;
9950 counterNewHeaders := counterNewHeaders + 1;
9951
9952 ELSIF(IsLogicGenerated(inComponentId) = 0)THEN
9953
9954 --The flag may be set by two reasons: the model was considered up-to-date or the model has already been
9955 --processed in this session. Only in the first case a header should exist in the database and we need
9956 --to load it into memory. In the second case it should be in the memory and may not exist in the database.
9957 --Bug #3150226.
9958
9959 nDebug := 1110003;
9960
9961 SELECT head.lce_header_id, max(text.seq_nbr) INTO nStructureHeaderId, nSequenceNbr
9962 FROM cz_lce_headers head, cz_lce_texts text
9963 WHERE head.deleted_flag = FLAG_NOT_DELETED
9964 AND head.net_type = LOGIC_NET_TYPE_STRUCTURE
9965 AND head.component_id = inComponentId
9966 AND head.lce_header_id = text.lce_header_id
9967 GROUP BY head.lce_header_id;
9968
9969 vSeqNbrByHeader(nStructureHeaderId) := nSequenceNbr + 1;
9970 END IF;
9971
9972 nDebug := 1110004;
9973
9974 vLogicText := 'CONTROL NOSPEC' || NewLine || 'VERSION 3 3' || NewLine ||
9975 'SETDEFAULTDELTA F' || NewLine || 'EFF , , ' || NewLine || NewLine ||
9976 'REM -- Structure file for component: ' || TO_CHAR(inComponentId) || NewLine || NewLine ||
9977 'OBJECT _ALWAYS_TRUE' || NewLine || 'MINMAX 1 1 _ALWAYS_TRUE' || NewLine ||
9978 'OBJECT _ALWAYS_FALSE' || NewLine ||
9979 'GS N' || NewLine || 'GL L _ALWAYS_TRUE' || NewLine || 'GR L _ALWAYS_FALSE' || NewLine;
9980
9981 nDebug := 1110005;
9982
9983 --This SELECT statement reads the whole 'virtual' tree under a non-virtual component which also
9984 --includes the non-virtual component itself. Non-virtual components underneath are included in
9985 --order to recurse, and this function will be called for every non-virtual component underneath.
9986 --The resulting order provided by this statement is used later when generating list of options
9987 --for an option feature.
9988
9989 SELECT ps_node_id, parent_id, item_id, minimum, maximum, name, intl_text_id, minimum_selected,
9990 maximum_selected, ps_node_type, initial_value, virtual_flag, feature_type, bom_required_flag,
9991 reference_id, persistent_node_id, effective_from, effective_until, effective_usage_mask,
9992 effectivity_set_id, decimal_qty_flag, ib_trackable, accumulator_flag, initial_num_value,
9993 instantiable_flag, shippable_item_flag, inventory_transactable_flag, assemble_to_order_flag,
9994 serializable_item_flag
9995 BULK COLLECT INTO
9996 ntPsNodeId, ntParentId, ntItemId, ntMinimum, ntMaximum, ntName, ntDescriptionId, ntMinimumSel,
9997 ntMaximumSel, ntPsNodeType, ntInitialValue, ntVirtualFlag, ntFeatureType, ntBomRequired,
9998 ntReferenceId, ntPersistentId, dtEffFrom, dtEffUntil, vtUsageMask,
9999 ntEffSetId, ntDecimalQty, ntIbTrackable, ntAccumulator, ntInitialNumValue,
10000 ntInstantiableFlag, ntShippableFlag, ntTransactableFlag, ntAtoFlag, ntSerializableFlag
10001 FROM cz_ps_nodes
10002 WHERE deleted_flag = FLAG_NOT_DELETED
10003 START WITH ps_node_id = inComponentId
10004 CONNECT BY PRIOR ps_node_id = parent_id
10005 AND (PRIOR virtual_flag IS NULL OR PRIOR virtual_flag = FLAG_VIRTUAL OR
10006 PRIOR ps_node_id = inComponentId);
10007
10008 nDebug := 1110006;
10009
10010 --Make sure there is some data returned
10011
10012 IF(ntPsNodeId.LAST IS NOT NULL)THEN
10013
10014 nDebug := 1110007;
10015
10016 --Having this dummy boundary node eliminates the necessity of potentially time
10017 --consuming boundary checks during the option feature options' list generation
10018
10019 ntParentId(ntPsNodeId.LAST + 1) := NEVER_EXISTS_ID;
10020
10021 --Prepare to start the main cycle
10022
10023 i := ntPsNodeId.FIRST;
10024
10025 WHILE(i <= ntPsNodeId.LAST) LOOP --Start the main structure generating cycle
10026 BEGIN
10027
10028 CurrentlyPacking := PACKING_GENERIC;
10029
10030 --Populate the 'global' arrays - required for rules generation
10031
10032 nDebug := 1110010;
10033
10034 IF(NOT glIndexByPsNodeId.EXISTS(ntPsNodeId(i)))THEN
10035
10036 IF(ntInitialNumValue(i) IS NOT NULL)THEN ntInitialValue(i) := TO_CHAR(ntInitialNumValue(i)); END IF;
10037
10038 glPsNodeId(globalCount) := ntPsNodeId(i);
10039 glItemId(globalCount) := ntItemId(i);
10040 glPsNodeType(globalCount) := ntPsNodeType(i);
10041 glParentId(globalCount) := ntParentId(i);
10042 glFeatureType(globalCount) := ntFeatureType(i);
10043 glName(globalCount) := ntName(i);
10044 glBomRequired(globalCount) := ntBomRequired(i);
10045 glMinimum(globalCount) := ntMinimum(i);
10046 glMaximum(globalCount) := ntMaximum(i);
10047 glMinimumSel(globalCount) := ntMinimumSel(i);
10048 glMaximumSel(globalCount) := ntMaximumSel(i);
10049 glVirtualFlag(globalCount) := ntVirtualFlag(i);
10050 glInitialValue(globalCount) := ntInitialValue(i);
10051
10052 --Indexing by ps_node_id, will be used in expressions generation to get back to
10053 --the structure.
10054
10055 glIndexByPsNodeId(ntPsNodeId(i)) := globalCount;
10056
10057 --These global arrays will be indexed differently because we only need to get
10058 --persistent_node_id or reference_id by ps_node_id. Probably, good indexing
10059 --option for some of the other global arrays, too.
10060
10061 glPersistentId(ntPsNodeId(i)) := ntPersistentId(i);
10062 glReferenceId(ntPsNodeId(i)) := ntReferenceId(i);
10063 glDecimalQty(ntPsNodeId(i)) := ntDecimalQty(i);
10064 glIbTrackable(ntPsNodeId(i)) := ntIbTrackable(i);
10065 glAccumulator(ntPsNodeId(i)) := ntAccumulator(i);
10066 glInstantiableFlag(ntPsNodeId(i)) := ntInstantiableFlag(i);
10067
10068 --Children of any node start right after the node. But then, the children list may
10069 --not be dense, because children may have their own children. So in order to find
10070 --all the children of a node we need to search the whole structure after the node.
10071 --Here we store the last child's index so that we need to search not the whole
10072 --structure up to the end but up to this last child's index.
10073
10074 nDebug := 1110011;
10075
10076 IF(ntParentId(i) IS NOT NULL)THEN
10077 glLastChildIndex(ntParentId(i)) := globalCount;
10078
10079 --This array is used in design chart rules generation and contains the number of children
10080 --of a node. We actually use it only for features and BOM option classes.
10081
10082 IF(NOT featOptionsCount.EXISTS(ntParentId(i)))THEN featOptionsCount(ntParentId(i)) := 0; END IF;
10083 featOptionsCount(ntParentId(i)) := featOptionsCount(ntParentId(i)) + 1;
10084 END IF;
10085
10086 IF(ntPsNodeType(i) = PS_NODE_TYPE_BOM_STANDARD AND ntIbTrackable(i) = FLAG_IB_TRACKABLE AND
10087 thisProjectType IN (MODEL_TYPE_PTO_MODEL, MODEL_TYPE_ATO_MODEL) AND
10088 glPsNodeType(glIndexByPsNodeId(ntParentId(i))) = PS_NODE_TYPE_BOM_MODEL AND
10089 glIbTrackable(ntParentId(i)) = FLAG_NOT_IB_TRACKABLE) THEN
10090
10091 --A trackable BOM Standard item cannot be a direct child of a non-trackable
10092 --ATO/PTO Model if this model is references from any Network Container model.
10093 --Re: bug #3644036.
10094
10095 IF(NOT h_containerReferred.EXISTS(ntParentId(i)))THEN
10096
10097 BEGIN
10098
10099 EXECUTE IMMEDIATE containerReferred INTO h_containerReferred(ntParentId(i)) USING ntParentId(i);
10100
10101 EXCEPTION
10102 WHEN NO_DATA_FOUND THEN
10103 h_containerReferred(ntParentId(i)) := 0;
10104 END;
10105 END IF;
10106
10107 IF(h_containerReferred(ntParentId(i)) = 1)THEN
10108
10109 errorMessage := thisProjectName;
10110 nParam := glIndexByPsNodeId(ntPsNodeId(i));
10111 RAISE CZ_S_TRACKABLE_STANDARD;
10112 END IF;
10113 END IF;
10114
10115 --Prepare the actual effective date interval for populating global effectivity dates.
10116 --First get the nominal effective date interval either from an effectivity set or
10117 --from the local values.
10118
10119 IF(ntEffSetId(i) IS NOT NULL)THEN
10120 IF(gvIndexBySetId.EXISTS(ntEffSetId(i)))THEN
10121 CurrentEffFrom := gvEffFrom(gvIndexBySetId(ntEffSetId(i)));
10122 CurrentEffUntil := gvEffUntil(gvIndexBySetId(ntEffSetId(i)));
10123 ELSE
10124 --This is a fatal error - data corruption.
10125 --'Invalid effectivity set associated with node ''%NODENAME'''
10126 errorMessage := CZ_UTILS.GET_TEXT('CZ_S_WRONG_EFFECTIVITY_SET', 'NODENAME', ntName(i));
10127 RAISE CZ_S_WRONG_EFFECTIVITY_SET;
10128 END IF;
10129 ELSE
10130 CurrentEffFrom := dtEffFrom(i);
10131 CurrentEffUntil := dtEffUntil(i);
10132 END IF;
10133 CurrentUsageMask := vtUsageMask(i);
10134
10135 --Make sure effective dates are not null, so that actual effective date interval
10136 --will have no null bounds too. Usage mask is not null anyway.
10137
10138 IF(CurrentEffFrom IS NULL)THEN CurrentEffFrom := EpochBeginDate; END IF;
10139 IF(CurrentEffUntil IS NULL)THEN CurrentEffUntil := EpochEndDate; END IF;
10140
10141 --If this is not a model or a root component, adjust the effectivity dates by
10142 --intersecting with parent's actual effectivity dates, which have already been
10143 --calculated because of the hierarchichal order of the query.
10144 --Actual effective date interval is the intersection of parent's actual effective
10145 --date interval with child's nominal effective date interval. Again, no nulls.
10146
10147 IF(ntParentId(i) IS NOT NULL)THEN
10148
10149 localCount := glIndexByPsNodeId(ntParentId(i));
10150 IF(glEffFrom(localCount) > CurrentEffFrom)THEN CurrentEffFrom := glEffFrom(localCount); END IF;
10151 IF(glEffUntil(localCount) < CurrentEffUntil)THEN CurrentEffUntil := glEffUntil(localcount); END IF;
10152
10153 --Adjust usage mask here. CurrentUsageMask is now OR-ed with glUsageMask(localCount)
10154 CurrentUsageMask := RAWTOHEX(UTL_RAW.BIT_OR(HEXTORAW(LPAD(CurrentUsageMask,16,'0')),HEXTORAW(glUsageMask(localCount))));
10155
10156 END IF;
10157
10158 --From now on the local variables (dtEff) or effectivity set, if defined, will contain
10159 --the nominal effective date interval while the global variables (glEff) will contain
10160 --the actual (intersected with parent) effective date interval.
10161 --The same is true for the usage mask nominal/actual values.
10162
10163 glEffFrom(globalCount) := CurrentEffFrom;
10164 glEffUntil(globalCount) := CurrentEffUntil;
10165 glUsageMask(globalCount) := CurrentUsageMask;
10166
10167 glHeaderByPsNodeId(ntPsNodeId(i)) := nStructureHeaderId;
10168 globalCount := globalCount + 1;
10169
10170 ELSE
10171
10172 localCount := glIndexByPsNodeId(ntPsNodeId(i));
10173 CurrentEffFrom := glEffFrom(localCount);
10174 CurrentEffUntil := glEffUntil(localCount);
10175 CurrentUsageMask := glUsageMask(localCount);
10176
10177 END IF;
10178
10179 nDebug := 1110012;
10180
10181 IF(isLogicGenerated.EXISTS(inComponentId))THEN
10182
10183 --We need to call the procedure for any non-virtual component (bug #2065239) and for any
10184 --component and reference.
10185
10186 IF(ntPsNodeType(i) IN (PS_NODE_TYPE_REFERENCE, PS_NODE_TYPE_CONNECTOR))THEN
10187
10188 --Check for circularity.
10189
10190 localCount := 0;
10191
10192 FOR n IN 1..globalLevel LOOP
10193 IF(globalStack(n) = ntReferenceId(i))THEN
10194
10195 --Circularity detected.
10196
10197 localCount := 1;
10198 EXIT;
10199 END IF;
10200 END LOOP;
10201
10202 IF(localCount = 0)THEN
10203
10204 globalLevel := globalLevel + 1;
10205 globalStack(globalLevel) := ntReferenceId(i);
10206 globalRef(globalLevel) := ntPsNodeId(i);
10207
10208 IF(ntPsNodeType(i) = PS_NODE_TYPE_REFERENCE)THEN
10209
10210 localMinString := TO_CHAR(ntMinimum(i));
10211 IF(localMinString IS NULL)THEN localMinString := '0'; END IF;
10212 localMaxString := TO_CHAR(ntMaximum(i));
10213 IF(localMaxString IS NULL)THEN localMaxString := '-1'; END IF;
10214
10215 --Store the information on the instantiability of the reference on the stack.
10216
10217 IF(localMinString = '1' AND localMaxString = '1')THEN
10218 globalInstance(globalLevel) := 0;
10219 ELSE
10220 globalInstance(globalLevel) := 1;
10221 END IF;
10222 ELSE
10223 --This is a connector and instantiability is not defined, but we need a value on
10224 --the stack.
10225
10226 globalInstance(globalLevel) := 0;
10227 END IF;
10228
10229 GENERATE_COMPONENT_TREE(ntReferenceId(i), ntReferenceId(i), NULL);
10230 globalLevel := globalLevel - 1;
10231
10232 --Bug #5003285. Need to move the propagation of trackable flag into this branch which
10233 --executes even if child model is up-to-date.
10234
10235 IF(ntPsNodeType(i) = PS_NODE_TYPE_REFERENCE AND rootProjectType = MODEL_TYPE_CONTAINER_MODEL AND
10236
10237 --All the following verifications are to be made only if the referenced model is
10238 --a BOM Model - bug #2509208.
10239
10240 glPsNodeType(glIndexByPsNodeId(ntReferenceId(i))) IN
10241 (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
10242
10243 --If the referenced model is trackable it may be a trackable leaf. However, if its
10244 --trackableAncestor flag exists, it has trackable children. In any case we need to
10245 --mark all of its ancestors and make sure their quantities are not greater than 1,
10246 --because the root is a container model here.
10247
10248 IF(glIbTrackable(ntReferenceId(i)) = FLAG_IB_TRACKABLE OR
10249 trackableAncestor.EXISTS(ntReferenceId(i)))THEN
10250
10251 trackableAncestor(ntPsNodeId(i)) := 1;
10252 PROPAGATE_TRACKABLE_ANCESTOR;
10253 END IF;
10254 END IF;
10255 END IF;
10256
10257 ELSIF(ntVirtualFlag(i) = FLAG_NON_VIRTUAL AND
10258 ntPsNodeType(i) IN (PS_NODE_TYPE_COMPONENT, PS_NODE_TYPE_PRODUCT) AND
10259 ntPsNodeId(i) <> inComponentId)THEN
10260
10261 --We emulate the component as a model with generated logic because we do not want to
10262 --generate anything but still want to follow everything underneath this component.
10263
10264 IsLogicGenerated(ntPsNodeId(i)) := 1;
10265
10266 --We can pass logic header as NULL because it will never be actually used.
10267
10268 GENERATE_COMPONENT_TREE(ntPsNodeId(i), inProjectId, 0);
10269 END IF;
10270
10271 --Bug #5003285. Need to move the propagation of trackable flag into this branch which
10272 --executes even if child model is up-to-date.
10273
10274 IF(rootProjectType = MODEL_TYPE_CONTAINER_MODEL AND
10275 ntPsNodeType(i) IN (PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD) AND
10276 glIbTrackable(ntPsNodeId(i)) = FLAG_IB_TRACKABLE)THEN
10277
10278 PROPAGATE_TRACKABLE_ANCESTOR;
10279
10280 --If the item is tangible, we should prohibit not only its ancestors but also itself
10281 --from being on the RHS of numeric rules - TSO with Equipment.
10282
10283 IF(ntShippableFlag(i) = '1')THEN trackableAncestor(ntPsNodeId(i)) := 2; END IF;
10284 END IF;
10285
10286 --If no logic already exists, generate the structure.
10287
10288 ELSE
10289
10290 GENERATE_EFFECTIVITY_LOGIC(CurrentEffFrom, CurrentEffUntil, CurrentUsageMask);
10291
10292 IF(ntPsNodeType(i) = PS_NODE_TYPE_OPTION)THEN
10293
10294 --We are in a feature's options. The important assumption here is that a feature
10295 --can have only options as it's children,so feature's children list is dense and
10296 --all the feature's children should be processed, and this list starts here.
10297 --In other words, we assume that as soon as we encountered the first option of a
10298 --feature, we will be dealing only with options of this feature until we process
10299 --all of them.
10300
10301 /*--The restriction is removed (bug #1746927)-----------------------------------
10302 --First make sure that there aren't too many options.
10303 IF(optionCounter > MAX_NUMBER_OF_OPTIONS)THEN
10304 --This will be fatal and terminate the logic generation
10305 --'Option feature has more than maximum allowed number of options, feature ''%FEATNAME'''
10306 errorMessage := CZ_UTILS.GET_TEXT('CZ_S_TOO_MANY_OPTIONS', 'FEATNAME', ntName(i));
10307 RAISE CZ_S_TOO_MANY_OPTIONS;
10308 END IF;
10309 ------------------------------------------------------------------------------*/
10310
10311 optionCounter := optionCounter + 1;
10312
10313 --Generate the option: OBJECT P_<OptID> R
10314 vLogicLine := 'OBJECT P_' || TO_CHAR(ntPersistentId(i)) || ' R' || NewLine;
10315
10316 --If this is the last option, we will generate the feature right here
10317
10318 IF(ntParentId(i + 1) <> ntParentId(i))THEN
10319
10320 --Done with options, ready to generate the feature, put in the stored
10321 --effectivity information.
10322
10323 PACK;
10324 GENERATE_EFFECTIVITY_LOGIC(FeatureEffFrom, FeatureEffUntil, FeatureUsageMask);
10325
10326 --This is the feature index
10327
10328 j := i - optionCounter;
10329
10330 --Generate the feature itself. Local variables here are inherited from the feature
10331 --generation section.
10332 --But before that adjust the minimum number of selected children to the actual number
10333 --of options - bug #2233795.
10334
10335 IF(ntMinimum(j) IS NOT NULL AND ntMinimum(j) > optionCounter)THEN
10336
10337 localMinString := TO_CHAR(optionCounter);
10338 END IF;
10339
10340 vLogicLine := 'SGN P_' || TO_CHAR(ntPersistentId(j)) || ' R ' || localMinString || ' ' ||
10341 localMaxString || ' _';
10342
10343 nDebug := 1110028;
10344
10345 --Generate the list of options for the feature
10346
10347 WHILE(j < i)LOOP
10348
10349 j := j + 1;
10350
10351 --This call is necessary here for wrapping
10352
10353 PACK;
10354 vLogicLine := ' P_' || TO_CHAR(ntPersistentId(j));
10355
10356 nDebug := 1110029;
10357
10358 END LOOP;
10359
10360 --We must put [new line] after the list of options
10361
10362 vLogicLine := vLogicLine || NewLine;
10363 j := i - optionCounter;
10364
10365 PACK;
10366 GENERATE_ACCUMULATOR(j);
10367 generatingFeature := 0;
10368
10369 --Minimum number of selected options greater than the actual number of options.
10370 --The feature is already generated and now will be reported.
10371
10372 IF(ntMinimum(j) IS NOT NULL AND ntMinimum(j) > optionCounter)THEN
10373
10374 RAISE CZ_S_ILLEGAL_OPTION_FEATURE;
10375 END IF;
10376
10377 END IF;
10378
10379 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_TOTAL OR
10380 ntPsNodeType(i) = PS_NODE_TYPE_RESOURCE)THEN
10381
10382 nDebug := 1110014;
10383
10384 --This is a total or resource: TOTAL P_<Tot/ResID> R [tot/res initial value]
10385
10386 vLogicLine := 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || ' R ' ||
10387 ntInitialValue(i) || NewLine;
10388 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_FEATURE)THEN
10389
10390 nDebug := 1110015;
10391
10392 --This is a feature, so consider different subtypes
10393
10394 IF(ntFeatureType(i) IS NULL OR ntFeatureType(i) = PS_NODE_FEATURE_TYPE_INTEGER)THEN
10395
10396 nDebug := 1110016;
10397
10398 --This is an integer feature: real integer or count
10399
10400 IF(ntMinimum(i) IS NULL OR ntMinimum(i) < 0)THEN
10401
10402 nDebug := 1110017;
10403
10404 --This is a real integer feature: TOTAL P_<FeatID> R [initial_value]
10405
10406 vLogicLine := 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || ' R ' ||
10407 ntInitialValue(i) || NewLine;
10408 ELSE
10409
10410 nDebug := 1110018;
10411
10412 --This is a count feature: OBJECT P_<FeatID> R [initial_value]
10413
10414 /* This is rolled back as a fix for the bug #1994924.
10415
10416 --If initial value is not specified and minimum value is greater than 0, we
10417 --define the initial value to be equal to the minimum value. Bug #1834581.
10418
10419 IF(ntInitialValue(i) IS NULL)THEN
10420 ntInitialValue(i) := ntMinimum(i);
10421 END IF;
10422 */
10423 vLogicLine := 'OBJECT P_' || TO_CHAR(ntPersistentId(i)) || ' R ' ||
10424 ntInitialValue(i) || NewLine;
10425 END IF;
10426 ELSIF(ntFeatureType(i) = PS_NODE_FEATURE_TYPE_FLOAT)THEN
10427
10428 nDebug := 1110019;
10429
10430 --This is a decimal feature: TOTAL P_<FeatID> R [initial_value]
10431
10432 /* This is rolled back as a fix for the bug #1994924.
10433
10434 --If initial value is not specified and minimum value is specified and is greater than 0,
10435 --we define the initial value to be equal to the minimum value. Bug #1834581.
10436
10437 IF(ntInitialValue(i) IS NULL AND ntMinimum(i) > 0)THEN
10438 ntInitialValue(i) := ntMinimum(i);
10439 END IF;
10440 */
10441 vLogicLine := 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || ' R ' ||
10442 ntInitialValue(i) || NewLine;
10443 ELSIF(ntFeatureType(i) = PS_NODE_FEATURE_TYPE_BOOLEAN)THEN
10444
10445 nDebug := 1110020;
10446
10447 --This is a boolean feature
10448
10449 vLogicLine := 'OBJECT P_' || TO_CHAR(ntPersistentId(i)) || ' R' || NewLine;
10450 IF(ntInitialValue(i) IS NOT NULL)THEN
10451 IF(ntInitialValue(i) = '1')THEN
10452
10453 nDebug := 1110021;
10454
10455 --Initial value is 'True', create a default rule from an always true object
10456 --toward this one
10457
10458 vLogicLine := vLogicLine || 'OBJECT D_' || TO_CHAR(ntPersistentId(i)) || '_IV' || NewLine ||
10459 'WITH _default = _ALWAYS_TRUE' || NewLine ||
10460 'GS R ... ' || TO_CHAR(ntDescriptionId(i)) || NewLine ||
10461 'GL N D_' || TO_CHAR(ntPersistentId(i)) || '_IV' || NewLine ||
10462 'GR N P_' || TO_CHAR(ntPersistentId(i)) || NewLine;
10463
10464 -- vLogicLine := vLogicLine || 'WITH _default = _ALWAYS_TRUE' || NewLine;
10465
10466 ELSIF(ntInitialValue(i) = '0')THEN
10467
10468 nDebug := 1110022;
10469
10470 --Initial value is 'False', create a temporary object and an additional
10471 --'negates' relation
10472
10473 vLogicLine := vLogicLine || 'OBJECT D_' || TO_CHAR(ntPersistentId(i)) || '_IV' || NewLine ||
10474 'WITH _default = _ALWAYS_TRUE' || NewLine ||
10475 'GS N ... ' || TO_CHAR(ntDescriptionId(i)) || NewLine ||
10476 'GL N D_' || TO_CHAR(ntPersistentId(i)) || '_IV' || NewLine ||
10477 'GR N P_' || TO_CHAR(ntPersistentId(i)) || NewLine;
10478
10479 ELSE
10480
10481 RAISE CZ_S_BAD_BOOLEAN_FEAT_VALUE;
10482
10483 END IF;
10484 END IF;
10485
10486 ELSIF(ntFeatureType(i) = PS_NODE_FEATURE_TYPE_STRING)THEN
10487
10488 nDebug := 1110023;
10489
10490 NULL;
10491
10492 /* Do not need to generate anything for text features.
10493
10494 --This is a text feature
10495
10496 vLogicLine := 'TEXT P_' || TO_CHAR(ntPersistentId(i)) || ' R "' ||
10497 ntInitialValue(i) || '"' || NewLine;
10498 */
10499 ELSIF(ntFeatureType(i) = PS_NODE_FEATURE_TYPE_OPTION)THEN
10500
10501 --Set the options counter
10502
10503 optionCounter := 0;
10504
10505 --Prepare Min, Max values for later use
10506 --Use intermediate variable instead of using NVL because this is faster
10507 --This values will be used also when generating the last option of the feature
10508
10509 localMinString := TO_CHAR(ntMinimum(i));
10510 IF(localMinString IS NULL)THEN localMinString := '0'; END IF;
10511 localMaxString := TO_CHAR(ntMaximum(i));
10512 IF(localMaxString IS NULL)THEN localMaxString := '-1'; END IF;
10513
10514 --Save feature's effective intervals and usage mask for feature generating type
10515
10516 FeatureEffFrom := CurrentEffFrom;
10517 FeatureEffUntil := CurrentEffUntil;
10518 FeatureUsageMask := CurrentUsageMask;
10519
10520 nDebug := 1110024;
10521
10522 --Check if there are any children, report if not
10523
10524 IF(ntParentId(i + 1) <> ntPsNodeId(i))THEN
10525
10526 --No options, still want to generate the feature even with empty options list
10527
10528 vLogicLine := 'SGN P_' || TO_CHAR(ntPersistentId(i)) || ' R ' || localMinString || ' ' ||
10529 localMaxString || ' _' || NewLine;
10530
10531 --No children, report the feature
10532 RAISE CZ_S_FEATURE_NO_CHILDREN;
10533 END IF;
10534
10535 --Now proceed with the cycle. As options of the feature directly follows it in memory,
10536 --we will be generating them right away. After the last option, the feature itself will
10537 --be generated (see options generating code).
10538
10539 generatingFeature := 1;
10540
10541 nDebug := 1110027;
10542
10543 ELSE
10544
10545 --'Unknown feature type, feature ''%FEATNAME'''
10546 errorMessage := CZ_UTILS.GET_TEXT('CZ_S_UNKNOWN_FEATURE_TYPE', 'FEATNAME', ntName(i));
10547 RAISE CZ_S_UNKNOWN_FEATURE_TYPE;
10548 END IF;
10549 ELSIF(ntPsNodeType(i) IN (PS_NODE_TYPE_COMPONENT, PS_NODE_TYPE_PRODUCT) AND
10550 ntVirtualFlag(i) = FLAG_NON_VIRTUAL)THEN
10551
10552 nDebug := 1110030;
10553
10554 --We don't want to go into an infinite cycle - don't call the procedure for the current
10555 --root component
10556
10557 IF(ntPsNodeId(i) <> inComponentId)THEN
10558
10559 --This is another non-virtual component. Call this function for it - recursion
10560 --Use intermediate variable instead of using NVL because this is faster
10561
10562 localMinString := TO_CHAR(ntMinimum(i));
10563 IF(localMinString IS NULL)THEN localMinString := '0'; END IF;
10564 localMaxString := TO_CHAR(ntMaximum(i));
10565 IF(localMaxString IS NULL)THEN localMaxString := '-1'; END IF;
10566
10567 vLogicLine := 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || '_MIN R ' || localMinString || NewLine ||
10568 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || '_MAX R ' || localMaxString || NewLine ||
10569 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || '_ACTUALCOUNT R 0' || NewLine;
10570
10571 GENERATE_COMPONENT_TREE(ntPsNodeId(i), inProjectId, nStructureHeaderId);
10572 END IF;
10573
10574 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_REFERENCE)THEN
10575
10576 nDebug := 1110031;
10577
10578 --Check for circularity.
10579
10580 localCount := 0;
10581 trackableContext := 0;
10582 instantiableContext := 0;
10583
10584 FOR n IN 1..globalLevel LOOP
10585
10586 IF(globalStack(n) = ntReferenceId(i))THEN
10587
10588 --Circularity detected.
10589
10590 localCount := 1;
10591 EXIT;
10592 END IF;
10593
10594 IF(glIbTrackable(globalStack(n)) = FLAG_IB_TRACKABLE)THEN
10595
10596 trackableContext := globalStack(n);
10597 END IF;
10598
10599 IF(globalInstance(n) = 1)THEN
10600
10601 instantiableContext := globalStack(n);
10602 END IF;
10603 END LOOP;
10604
10605 localMinString := TO_CHAR(ntMinimum(i));
10606 IF(localMinString IS NULL)THEN localMinString := '0'; END IF;
10607 localMaxString := TO_CHAR(ntMaximum(i));
10608 IF(localMaxString IS NULL)THEN localMaxString := '-1'; END IF;
10609
10610 IF(ntVirtualFlag(i) = FLAG_NON_VIRTUAL)THEN
10611
10612 vLogicLine := 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || '_MIN R ' || localMinString || NewLine ||
10613 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || '_MAX R ' || localMaxString || NewLine ||
10614 'TOTAL P_' || TO_CHAR(ntPersistentId(i)) || '_ACTUALCOUNT R 0' || NewLine;
10615 END IF;
10616
10617 IF(localCount = 0)THEN
10618
10619 --Follow the reference, doesn't affect the current LCE file.
10620 --Use intermediate variable instead of using NVL because this is faster.
10621 --Maintain the stack of references - needed to be able to detect dead-loops.
10622
10623 globalLevel := globalLevel + 1;
10624 globalStack(globalLevel) := ntReferenceId(i);
10625 globalRef(globalLevel) := ntPsNodeId(i);
10626
10627 --Store the information on the instantiability of the reference on the stack.
10628
10629 IF(localMinString = '1' AND localMaxString = '1')THEN
10630 globalInstance(globalLevel) := 0;
10631 ELSE
10632 globalInstance(globalLevel) := 1;
10633 END IF;
10634
10635 GENERATE_COMPONENT_TREE(ntReferenceId(i), ntReferenceId(i), NULL);
10636 globalLevel := globalLevel - 1;
10637
10638 IF(rootProjectType = MODEL_TYPE_CONTAINER_MODEL AND
10639
10640 --All the following verifications are to be made only if the referenced model is
10641 --a BOM Model - bug #2509208.
10642
10643 glPsNodeType(glIndexByPsNodeId(ntReferenceId(i))) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
10644
10645 errorMessage := glName(glIndexByPsNodeId(ntReferenceId(i)));
10646
10647 --If this is a network container model, every reference to a trackable model should
10648 --have exactly minimum = 0 and maximum = -1. This validation must be made after the
10649 --referenced model is processed so that its IB_TRACKABLE flag has become available.
10650 --IB_TRACKABLE flag for the instantiably referenced model should not be null.
10651
10652 IF(glIbTrackable(ntReferenceId(i)) IS NULL)THEN
10653
10654 RAISE CZ_S_NO_TRACKABLE_FLAG;
10655
10656 ELSIF(trackableContext = 0 AND glIbTrackable(ntReferenceId(i)) = FLAG_IB_TRACKABLE)THEN
10657
10658 --This is a trackable instance model, make additional verifications.
10659
10660 IF(instanceModel.EXISTS(ntReferenceId(i)) AND
10661 (globalLevel > 1 OR instanceModel(ntReferenceId(i)) > 1))THEN
10662
10663 --Multiple occurrences of a trackable instance model. We allow them only if all
10664 --of them are immediate children of the container model, because they may have
10665 --different effectivity ranges.
10666
10667 nParam := glIndexByPsNodeId(globalStack(globalLevel - 1));
10668 RAISE CZ_S_MULTIPLE_TRACKABLE;
10669
10670 ELSIF(instantiableContext > 0)THEN
10671
10672 --One of the ancestors of the trackable instance model is multiply instantiable.
10673
10674 nParam := glIndexByPsNodeId(instantiableContext);
10675 RAISE CZ_S_MULTIPLE_INSTANCES;
10676
10677 ELSIF(localMinString <> '0' OR localMaxString <> '-1')THEN
10678
10679 --Incorrect instance numbers for a reference to a trackable instance model.
10680
10681 RAISE CZ_S_INCORRECT_CONTAINER;
10682
10683 ELSE
10684
10685 instanceModel(ntReferenceId(i)) := globalLevel;
10686 END IF;
10687 END IF;
10688
10689 --If the referenced model is trackable it may be a trackable leaf. However, if its
10690 --trackableAncestor flag exists, it has trackable children. In any case we need to
10691 --mark all of its ancestors and make sure their quantities are not greater than 1,
10692 --because the root is a container model here.
10693
10694 IF(glIbTrackable(ntReferenceId(i)) = FLAG_IB_TRACKABLE OR
10695 trackableAncestor.EXISTS(ntReferenceId(i)))THEN
10696
10697 trackableAncestor(ntPsNodeId(i)) := 1;
10698 PROPAGATE_TRACKABLE_ANCESTOR;
10699 END IF;
10700 END IF;
10701 END IF;
10702
10703 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_CONNECTOR)THEN
10704
10705 --Go and generate the connection target. At least we need to have its structure in
10706 --memory, but there is also a versioning problem.
10707 --Check for circularity.
10708
10709 localCount := 0;
10710 trackableContext := 0;
10711
10712 FOR n IN 1..globalLevel LOOP
10713 IF(globalStack(n) = ntReferenceId(i))THEN
10714
10715 --Circularity detected.
10716
10717 localCount := 1;
10718 EXIT;
10719 END IF;
10720
10721 IF(glIbTrackable(globalStack(n)) = FLAG_IB_TRACKABLE)THEN
10722
10723 trackableContext := globalStack(n);
10724 END IF;
10725 END LOOP;
10726
10727 IF(localCount = 0)THEN
10728
10729 globalLevel := globalLevel + 1;
10730 globalStack(globalLevel) := ntReferenceId(i);
10731 globalRef(globalLevel) := ntPsNodeId(i);
10732
10733 --This is a connector and instantiability is not defined, but we need a value on
10734 --the stack.
10735
10736 globalInstance(globalLevel) := 0;
10737
10738 GENERATE_COMPONENT_TREE(ntReferenceId(i), ntReferenceId(i), NULL);
10739 globalLevel := globalLevel - 1;
10740
10741 IF(rootProjectType = MODEL_TYPE_CONTAINER_MODEL)THEN
10742
10743 --Definition: trackable instance model is a trackable model that has no trackable
10744 --ancestors. In a container model no connectors to trackable instance models are
10745 --allowed. In other words, any connector to a trackable model in a container model
10746 --should be inside a trackable child of the container model.
10747
10748 IF(glIbTrackable(ntReferenceId(i)) = FLAG_IB_TRACKABLE AND trackableContext = 0)THEN
10749
10750 errorMessage := thisProjectName;
10751 nParam := glIndexByPsNodeId(ntReferenceId(i));
10752 RAISE CZ_S_CONNECTOR_TRACKABLE;
10753 END IF;
10754
10755 --Inside a trackable model no connector to a non-trackable model is allowed on any
10756 --level in a container model.
10757
10758 IF((glIbTrackable(ntReferenceId(i)) IS NULL OR glIbTrackable(ntReferenceId(i)) <> FLAG_IB_TRACKABLE) AND
10759 trackableContext > 0)THEN
10760
10761 errorMessage := glName(glIndexByPsNodeId(ntReferenceId(i)));
10762 nParam := glIndexByPsNodeId(trackableContext);
10763 RAISE CZ_S_CONNECT_NONTRACKABLE;
10764 END IF;
10765 END IF;
10766 END IF;
10767
10768 ELSIF(ntPsNodeType(i) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
10769
10770 nDebug := 1110032;
10771
10772 --Run the TSO with Equipment validations before generating logic.
10773
10774 IF(rootProjectType = MODEL_TYPE_CONTAINER_MODEL OR
10775 thisProjectType = MODEL_TYPE_CONTAINER_MODEL)THEN
10776
10777 errorMessage := thisProjectName;
10778 thisName := ntName(i);
10779 parentName := '';
10780 IF(ntParentId(i) IS NOT NULL)THEN parentName := glName(glIndexByPsNodeId(ntParentId(i))); END IF;
10781
10782 IF(ntShippableFlag(i) IS NULL OR ntTransactableFlag(i) IS NULL OR
10783 ntAtoFlag(i) IS NULL OR ntSerializableFlag(i) IS NULL) THEN
10784
10785 --'The BOM Model ''%MODELNAME'' is out of date. Please refresh the Model by running the Refresh a Single
10786 -- Configuration Model concurrent program and then regenerate the Active Model.'
10787
10788 RAISE CZ_LCE_MODEL_OUTOFDATE;
10789 END IF; --The new flags are null, need to refresh.
10790
10791 IF((ntPsNodeType(i) IN (PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_MODEL)) AND
10792 (ntShippableFlag(i) = '1' OR ntTransactableFlag(i) = '1'))THEN
10793
10794 --'Incorrect BOM Model or Option Class ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
10795 -- Only BOM Standard Items can be shippable and inventory transactable.'
10796
10797 RAISE CZ_LCE_INCORRECT_BOM;
10798 END IF; --Flags are set for a non-Standard item node.
10799
10800 IF(ntPsNodeType(i) = PS_NODE_TYPE_BOM_STANDARD)THEN
10801 IF(ntShippableFlag(i) <> ntTransactableFlag(i))THEN
10802
10803 --'Incorrect BOM Standard Item ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
10804 -- All shippable items should be inventory transactable and vice versa.'
10805
10806 RAISE CZ_LCE_INCORRECT_ITEM;
10807 END IF; -- ntShippableFlag <> ntTransactableFlag.
10808
10809 IF(ntShippableFlag(i) = '1' AND ((ntAtoFlag(i) <> '0') OR (NVL(ntIbTrackable(i), '0') <> '1')))THEN
10810
10811 --'Incorrect BOM Standard Item ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
10812 -- All shippable items should be trackable non-ATO standard items with maximum quantity 1.'
10813
10814 RAISE CZ_LCE_INCORRECT_TANGIBLE;
10815 END IF; --ntShippableFlag = '1'.
10816
10817 IF(ntShippableFlag(i) = '1' AND ntSerializableFlag(i) = '0')THEN
10818
10819 --'Incorrect BOM Standard Item ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
10820 -- All shippable items should be serializable trackable non-ATO standard items.'
10821
10822 RAISE CZ_LCE_INCORRECT_SHIPPABLE;
10823 END IF; --ntShippableFlag = '1' AND ntSerializableFlag = '0';
10824 END IF; --Standard Item.
10825 END IF; --MACD Container.
10826
10827 nDebug := 1110033;
10828
10829 --Generate header.
10830
10831 vLogicLine := 'BOM P_' || TO_CHAR(ntPersistentId(i)) || ' R ';
10832
10833 --BOM modifier.
10834
10835 IF(ntPsNodeType(i) = PS_NODE_TYPE_BOM_STANDARD)THEN
10836 vLogicLine := vLogicLine || 'S';
10837 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_BOM_OPTIONCLASS)THEN
10838 vLogicLine := vLogicLine || 'O';
10839 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_BOM_MODEL)THEN
10840 vLogicLine := vLogicLine || 'M';
10841
10842 --This is a BOM model, it can be only the root model, so that thisProjectType and
10843 --thisProjectName are currently referring to it.
10844
10845 IF(ntIbTrackable(i) = FLAG_IB_TRACKABLE AND thisProjectType = MODEL_TYPE_CONTAINER_MODEL)THEN
10846
10847 --A network container model should not be trackable.
10848
10849 errorMessage := thisProjectName;
10850 RAISE CZ_S_TRACKABLE_CONTAINER;
10851 END IF;
10852 ELSE
10853
10854 --'Unknown BOM node type, node ''%NODENAME'''
10855 errorMessage := CZ_UTILS.GET_TEXT('CZ_S_UNKNOWN_BOM_NODE_TYPE', 'NODENAME', ntName(i));
10856 RAISE CZ_S_UNKNOWN_BOM_NODE_TYPE;
10857 END IF;
10858
10859 IF(ntPsNodeType(i) IN (PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD) AND
10860 glIbTrackable(ntPsNodeId(i)) = FLAG_IB_TRACKABLE)THEN
10861
10862 --Trackable Standard Items/Option Classes are not allowed as immediate children of a
10863 --network container model.
10864
10865 IF(thisProjectType = MODEL_TYPE_CONTAINER_MODEL AND
10866 glPsNodeType(glIndexByPsNodeId(ntParentId(i))) = PS_NODE_TYPE_BOM_MODEL)THEN
10867
10868 errorMessage := thisProjectName;
10869 nParam := glIndexByPsNodeId(ntPsNodeId(i));
10870 RAISE CZ_S_TRACKABLE_CHILDREN;
10871 END IF;
10872
10873 --As this is a trackable Standard Item or Option Class we need to mark all of its
10874 --ancestors and make sure their quantities are not greater than 1, if the root is
10875 --a container model.
10876
10877 IF(rootProjectType = MODEL_TYPE_CONTAINER_MODEL)THEN
10878
10879 PROPAGATE_TRACKABLE_ANCESTOR;
10880
10881 --If the item is tangible, we should prohibit not only its ancestors but also itself
10882 --from being on the RHS of numeric rules - TSO with Equipment.
10883
10884 IF(ntShippableFlag(i) = '1')THEN trackableAncestor(ntPsNodeId(i)) := 2; END IF;
10885 END IF;
10886 END IF;
10887
10888 --Add the decimal quantity modifier if necessary
10889
10890 IF(ntDecimalQty(i) = FLAG_DECIMAL_QTY)THEN
10891 vLogicLine := vLogicLine || 'D';
10892 END IF;
10893
10894 nDebug := 1110034;
10895
10896 --BOM required flag + minimum which is always 0
10897
10898 IF(ntBomRequired(i) = FLAG_BOM_REQUIRED)THEN
10899 vLogicLine := vLogicLine || ' RC 0 ';
10900 ELSE
10901 vLogicLine := vLogicLine || ' NRC 0 ';
10902 END IF;
10903
10904 nDebug := 1110035;
10905
10906 --Maximum selected
10907
10908 IF(ntMaximumSel(i) IS NOT NULL)THEN
10909 vLogicLine := vLogicLine || TO_CHAR(ntMaximumSel(i)) || ' ';
10910 ELSE
10911 vLogicLine := vLogicLine || '-1 ';
10912 END IF;
10913
10914 nDebug := 1110036;
10915
10916 --Parent 'logic' name if any
10917
10918 IF(ntParentId(i) IS NOT NULL AND
10919 glPsNodeType(glIndexByPsNodeId(ntParentId(i))) IN (PS_NODE_TYPE_BOM_MODEL, PS_NODE_TYPE_BOM_OPTIONCLASS, PS_NODE_TYPE_BOM_STANDARD))THEN
10920
10921 --Fix for the bug #1745394. If a BOM parent is of decimal quantity and it's child is of
10922 --integer quantity, fatal error will be raised.
10923
10924 IF(glDecimalQty(ntParentId(i)) = FLAG_DECIMAL_QTY AND ntDecimalQty(i) = FLAG_INTEGER_QTY)THEN
10925
10926 --'Node ''%CHILDNAME'' must allow decimal quantity since its parent ''%PARENTNAME'' allows decimal quantity'
10927 errorMessage := CZ_UTILS.GET_TEXT('CZ_S_INCONSISTENT_QUANTITY', 'CHILDNAME', ntName(i),
10928 'PARENTNAME', glName(glIndexByPsNodeId(ntParentId(i))));
10929 RAISE CZ_S_INCONSISTENT_QUANTITY;
10930 END IF;
10931
10932 vLogicLine := vLogicLine || 'P_' || TO_CHAR(glPersistentId(ntParentId(i))) || ' ';
10933 END IF;
10934
10935 nDebug := 1110037;
10936
10937 --Default quantity. If initial_value is not null and can't be converted to
10938 --a number the VALUE_ERROR exception will be raised. We catch this one and
10939 --re-raise our own exception for better reporting.
10940
10941 BEGIN
10942 IF(ntInitialValue(i) IS NOT NULL AND TO_NUMBER(ntInitialValue(i)) > 0)THEN
10943 vLogicLine := vLogicLine || ntInitialValue(i) || ' ... ' || ntDescriptionId(i) || NewLine;
10944 ELSE
10945 vLogicLine := vLogicLine || '0' || ' ... ' || ntDescriptionId(i) || NewLine;
10946 END IF;
10947 EXCEPTION
10948 WHEN VALUE_ERROR THEN
10949 RAISE CZ_S_WRONG_INITIAL_VALUE;
10950 END;
10951
10952 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_FEATUREGROUP)THEN
10953
10954 NULL;
10955
10956 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_COMPONENT)THEN
10957
10958 NULL;
10959
10960 ELSIF(ntPsNodeType(i) = PS_NODE_TYPE_PRODUCT)THEN
10961
10962 NULL;
10963
10964 ELSE
10965
10966 --'Unknown node type, node ''%NODENAME'''
10967 errorMessage := CZ_UTILS.GET_TEXT('CZ_S_UNKNOWN_NODE_TYPE', 'NODENAME', ntName(i));
10968 RAISE CZ_S_UNKNOWN_NODE_TYPE;
10969 END IF;
10970 END IF; --End of the IF block of 'if logic does not already exist' inside the main loop
10971
10972 --This exception handler may be used to catch the 'logic item'-level exceptions
10973 --that shouldn't stop the process. If an exception is re-raised here it becomes
10974 --a fatal exception (warning vs. errors).
10975
10976 EXCEPTION
10977 WHEN CZ_S_BAD_BOOLEAN_FEAT_VALUE THEN
10978 --'Bad boolean feature value, feature ''%FEATNAME'''
10979 REPORT(CZ_UTILS.GET_TEXT('CZ_S_BAD_BOOLEAN_FEAT_VALUE', 'FEATNAME', ntName(i)), 1);
10980 WHEN CZ_S_FEATURE_NO_CHILDREN THEN
10981 --'Option feature has no children, feature ''%FEATNAME'''
10982 REPORT(CZ_UTILS.GET_TEXT('CZ_S_FEATURE_NO_CHILDREN', 'FEATNAME', ntName(i)), 1);
10983 WHEN CZ_S_ILLEGAL_OPTION_FEATURE THEN
10984 --'Feature ''%FEATNAME'' has no options or fewer options than its minimum count, feature ''%FEATNAME'''
10985 REPORT(CZ_UTILS.GET_TEXT('CZ_S_ILLEGAL_OPTION_FEATURE', 'FEATNAME', ntName(j)), 1);
10986 WHEN CZ_S_WRONG_INITIAL_VALUE THEN
10987 --'Initial value of BOM node is not null and can not be converted to number, node ''%NODENAME'''
10988 REPORT(CZ_UTILS.GET_TEXT('CZ_S_WRONG_INITIAL_VALUE', 'NODENAME', ntName(i)), 1);
10989
10990 --Fatal exceptions section. Exceptions are re-raised to be reported at the higher level.
10991
10992 WHEN CZ_S_DEADLOOP_DETECTED THEN --Currently never thrown.
10993 --As per bug #3593513, when thrown should probably be moved to the place where thrown. Otherwise going up from
10994 --the recursion overwites the message substituting incorrect names.
10995
10996 --'An infinite loop detected: models ''%MODELNAME'' and ''%CHILDNAME'' reference each other'
10997 errorMessage := CZ_UTILS.GET_TEXT('CZ_S_DEADLOOP_DETECTED', 'MODELNAME', glName(glIndexByPsNodeId(globalStack(globalLevel))),
10998 'CHILDNAME', glName(glIndexByPsNodeId(globalStack(nParam))));
10999 RAISE;
11000 END;
11001
11002 --This procedure implements wrapping. A call to it is included in options list generation
11003 --for an option feature above
11004
11005 PACK;
11006
11007 nDebug := 1110040;
11008
11009 IF(NOT IsLogicGenerated.EXISTS(inComponentId))THEN
11010
11011 --generatingFeature is set to 1 when we step over an option feature with actual options. It will
11012 --be unset when we finally generate the feature after all of its options. But while generating
11013 --the options we want to call this procedure for every of them. This is why we check the type
11014 --and if it is an option, call the procedure even though the flag is set.
11015
11016 IF(generatingFeature = 0 OR ntPsNodeType(i) = PS_NODE_TYPE_OPTION)THEN GENERATE_ACCUMULATOR(i); END IF;
11017 END IF;
11018
11019 --Increase the main cycle counter
11020
11021 i := i + 1;
11022
11023 END LOOP; --End of the main structure generation cycle
11024
11025 nDebug := 1110038;
11026
11027 ELSE --IF 'there is some data returned'
11028
11029 --The project is empty, stop here.
11030
11031 errorMessage := thisProjectName;
11032 RAISE CZ_S_NO_DATA_IN_PROJECT;
11033
11034 END IF; --Ends the ELSE block of IF 'there is some data returned'
11035
11036 IF(NOT IsLogicGenerated.EXISTS(inComponentId))THEN
11037
11038 --Flush the buffer
11039
11040 IF(vLogicText IS NOT NULL)THEN
11041 INSERT INTO cz_lce_texts (lce_header_id, seq_nbr, lce_text) VALUES
11042 (nStructureHeaderId, nSequenceNbr, vLogicText);
11043 vLogicText := NULL;
11044 END IF;
11045
11046 --Remember the next sequence number for this logic file. Will be used in
11047 --numeric rules generation for accumulators.
11048
11049 vSeqNbrByHeader(nStructureHeaderId) := nSequenceNbr + 1;
11050
11051 IF(TwoPhaseCommit = 0)THEN COMMIT; END IF;
11052 END IF;
11053
11054 nDebug := 1110039;
11055
11056 --If a model, generate rules and set the logic generated flag.
11057
11058 IF(inParentLogicHeaderId IS NULL)THEN
11059
11060 --Generate model's rules and expressions if necessary
11061
11062 IF(NOT IsLogicGenerated.EXISTS(inComponentId))THEN
11063 GENERATE_RULES;
11064 IsLogicGenerated(inComponentId) := 1;
11065 END IF;
11066 END IF;
11067 END; --GENERATE_COMPONENT_TREE
11068 ---------------------------------------------------------------------------------------
11069 PROCEDURE COMMIT_HEADERS IS
11070 localOldHeaders tIntegerArray;
11071 nCount PLS_INTEGER := 1;
11072 localComponent NUMBER := NULL; --kdande; Bug 6881902; 11-Mar-2008
11073 BEGIN
11074
11075 FOR i IN 1..NewHeaders.COUNT LOOP
11076 IF(((NOT IsLogicGenerated.EXISTS(NewHeadersComponents(i))) OR IsLogicGenerated(NewHeadersComponents(i)) = 1) AND
11077 (localComponent IS NULL OR NewHeadersComponents(i) <> localComponent))THEN
11078
11079 localOldHeaders.DELETE;
11080
11081 SELECT lce_header_id BULK COLLECT INTO localOldHeaders FROM cz_lce_headers
11082 WHERE deleted_flag = FLAG_NOT_DELETED
11083 AND devl_project_id = NewHeadersComponents(i);
11084
11085 FOR j IN 1..localOldHeaders.COUNT LOOP
11086 OldHeaders(nCount) := localOldHeaders(j);
11087 nCount := nCount + 1;
11088 END LOOP;
11089
11090 localComponent := NewHeadersComponents(i);
11091 END IF;
11092 END LOOP;
11093
11094 FORALL i IN 1..OldHeaders.COUNT
11095 UPDATE cz_lce_headers SET deleted_flag = FLAG_DELETED
11096 WHERE lce_header_id = OldHeaders(i);
11097
11098 FORALL i IN 1..OldHeaders.COUNT
11099 UPDATE cz_lce_load_specs SET deleted_flag = FLAG_DELETED
11100 WHERE lce_header_id = OldHeaders(i);
11101
11102 FORALL i IN 1..NewHeaders.COUNT
11103 UPDATE cz_lce_headers SET deleted_flag = FLAG_NOT_DELETED
11104 WHERE lce_header_id = NewHeaders(i);
11105
11106 FORALL i IN 1..NewHeaders.COUNT
11107 UPDATE cz_lce_load_specs SET deleted_flag = FLAG_NOT_DELETED
11108 WHERE lce_header_id = NewHeaders(i);
11109
11110 cz_security_pvt.unlock_model(1.0, FND_API.G_TRUE, l_locked_models, l_lock_status, l_msg_count, l_msg_data);
11111
11112 IF(l_lock_status <> FND_API.G_RET_STS_SUCCESS)THEN
11113 FOR jmessage IN 1..l_msg_count LOOP
11114 REPORT(fnd_msg_pub.get(jmessage, FND_API.G_FALSE), 0);
11115 END LOOP;
11116 END IF;
11117
11118 IF(TwoPhaseCommit = 0)THEN COMMIT; END IF;
11119 END;
11120 ---------------------------------------------------------------------------------------
11121 PROCEDURE ROLLBACK_HEADERS IS
11122 BEGIN
11123
11124 FORALL i IN 1..NewHeaders.COUNT
11125 UPDATE cz_lce_headers SET deleted_flag = FLAG_DELETED
11126 WHERE lce_header_id = NewHeaders(i);
11127
11128 FORALL i IN 1..NewHeaders.COUNT
11129 UPDATE cz_lce_load_specs SET deleted_flag = FLAG_DELETED
11130 WHERE lce_header_id = NewHeaders(i);
11131
11132 IF(OldHeaders.COUNT > 0)THEN
11133
11134 FORALL i IN 1..OldHeaders.COUNT
11135 UPDATE cz_lce_headers SET deleted_flag = FLAG_NOT_DELETED
11136 WHERE lce_header_id = OldHeaders(i);
11137
11138 FORALL i IN 1..OldHeaders.COUNT
11139 UPDATE cz_lce_load_specs SET deleted_flag = FLAG_NOT_DELETED
11140 WHERE lce_header_id = OldHeaders(i);
11141 END IF;
11142
11143 cz_security_pvt.unlock_model(1.0, FND_API.G_TRUE, l_locked_models, l_lock_status, l_msg_count, l_msg_data);
11144
11145 IF(l_lock_status <> FND_API.G_RET_STS_SUCCESS)THEN
11146 FOR jmessage IN 1..l_msg_count LOOP
11147 REPORT(fnd_msg_pub.get(jmessage, FND_API.G_FALSE), 0);
11148 END LOOP;
11149 END IF;
11150
11151 IF(TwoPhaseCommit = 0)THEN COMMIT; END IF;
11152
11153 EXCEPTION
11154 WHEN OTHERS THEN
11155 --'Fatal error. Logic header maintainance not completed. Unable to rollback changes because of %ERRORTEXT'
11156 REPORT(CZ_UTILS.GET_TEXT('CZ_G_UNABLE_TO_ROLLBACK', 'ERRORTEXT', SQLERRM), 0);
11157 END;
11158 ---------------------------------------------------------------------------------------
11159 FUNCTION CHECK_DATES(inModelId IN NUMBER, inLogicUpdate IN DATE, inHeaderCreated IN DATE)
11160 RETURN PLS_INTEGER IS
11161
11162 c_model refCursor;
11163 childFlag PLS_INTEGER;
11164 thisFlag PLS_INTEGER := GENERATION_NOT_REQUIRED;
11165 childModelId cz_devl_projects.devl_project_id%TYPE;
11166 childLogicUpdate cz_devl_projects.last_logic_update%TYPE;
11167 childHeaderCreated cz_lce_headers.creation_date%TYPE;
11168
11169 BEGIN
11170
11171 IF(NOT modelChecked.EXISTS(inModelId))THEN
11172
11173 modelChecked(inModelId) := 1;
11174
11175 OPEN c_model FOR logicSQL USING inModelId;
11176 LOOP
11177 FETCH c_model INTO childModelId, childLogicUpdate, childHeaderCreated;
11178 EXIT WHEN c_model%NOTFOUND;
11179
11180 childFlag := CHECK_DATES(childModelId, childLogicUpdate, childHeaderCreated);
11181
11182 IF(thisFlag = GENERATION_NOT_REQUIRED AND
11183 (childFlag = GENERATION_REQUIRED OR inHeaderCreated < childLogicUpdate))THEN
11184 thisFlag := GENERATION_REQUIRED;
11185 END IF;
11186 END LOOP;
11187 CLOSE c_model;
11188 END IF;
11189
11190 IF(thisFlag = GENERATION_NOT_REQUIRED AND inHeaderCreated < inLogicUpdate)THEN
11191 thisFlag := GENERATION_REQUIRED;
11192 END IF;
11193
11194 IF(thisFlag = GENERATION_NOT_REQUIRED)THEN
11195 IsLogicGenerated(inModelId) := 0;
11196 END IF;
11197 RETURN thisFlag;
11198 END;
11199 ---------------------------------------------------------------------------------------
11200 BEGIN --GENERATE_LOGIC_
11201
11202 --Bug #4587682. Save current nls numeric characters and set the standard characters.
11203
11204 SELECT value INTO StoreNlsCharacters FROM NLS_SESSION_PARAMETERS
11205 WHERE UPPER(parameter) = 'NLS_NUMERIC_CHARACTERS';
11206
11207 SET_NLS_CHARACTERS(NlsNumericCharacters);
11208
11209 BEGIN
11210
11211 --Database settings processing section
11212
11213 BEGIN
11214
11215 --Get the commit block size - the number of records inserted into cz_lce_texts
11216 --after which the transaction is commited, if commit is not disabled at all by
11217 --TwoPhaseCommit parameter set to 1.
11218
11219 SELECT TO_NUMBER(value) INTO CommitBlockSize
11220 FROM cz_db_settings
11221 WHERE LOWER(setting_id) = COMMIT_BLOCK_SETTING_ID
11222 AND LOWER(section_name) = DBSETTINGS_SECTION_NAME;
11223
11224 IF(CommitBlockSize <= 0) THEN CommitBlockSize := DEFAULT_COMMIT_BLOCK_SIZE; END IF;
11225
11226 EXCEPTION
11227 WHEN OTHERS THEN
11228 CommitBlockSize := DEFAULT_COMMIT_BLOCK_SIZE;
11229 END;
11230
11231 /* Making the optimizations unconditional, cz_db_settings ignored.
11232 BEGIN
11233
11234 --Get the NotTrue optimization flag, no optimization by default.
11235
11236 SELECT DECODE(LOWER(value), '1', 1, 'on', 1, 'y', 1, 'yes', 1,'true', 1, 'enable', 1,
11237 '0', 0, 'off', 0, 'n', 0, 'no', 0,'false', 0, 'disable', 0,
11238 0) --default value
11239 INTO OptimizeNotTrue
11240 FROM cz_db_settings
11241 WHERE LOWER(setting_id) = OPTIMIZE_NOTTRUE_SETTING_ID
11242 AND LOWER(section_name) = DBSETTINGS_SECTION_NAME;
11243
11244 EXCEPTION
11245 WHEN OTHERS THEN
11246 OptimizeNotTrue := 0;
11247 END;
11248
11249 BEGIN
11250
11251 --Get the AllOf/AnyOf optimization flag, no optimization by default.
11252
11253 SELECT DECODE(LOWER(value), '1', 1, 'on', 1, 'y', 1, 'yes', 1,'true', 1, 'enable', 1,
11254 '0', 0, 'off', 0, 'n', 0, 'no', 0,'false', 0, 'disable', 0,
11255 0) --default value
11256 INTO OptimizeAllAnyOf
11257 FROM cz_db_settings
11258 WHERE LOWER(setting_id) = OPTIMIZE_ALLANYOF_SETTING_ID
11259 AND LOWER(section_name) = DBSETTINGS_SECTION_NAME;
11260
11261 EXCEPTION
11262 WHEN OTHERS THEN
11263 OptimizeAllAnyOf := 0;
11264 END;
11265
11266 BEGIN
11267
11268 --Get the Change Children Order flag, no change by default.
11269 --Currently will change children order when generating AllOf/AnyOf.
11270
11271 SELECT DECODE(LOWER(value), '1', 1, 'on', 1, 'y', 1, 'yes', 1,'true', 1, 'enable', 1,
11272 '0', 0, 'off', 0, 'n', 0, 'no', 0,'false', 0, 'disable', 0,
11273 0) --default value
11274 INTO ChangeChildrenOrder
11275 FROM cz_db_settings
11276 WHERE LOWER(setting_id) = CHILDREN_ORDER_SETTING_ID
11277 AND LOWER(section_name) = DBSETTINGS_SECTION_NAME;
11278
11279 EXCEPTION
11280 WHEN OTHERS THEN
11281 ChangeChildrenOrder := 0;
11282 END;
11283 */
11284
11285 --Enable all three optimizations here ignoring cz_db_settings.
11286
11287 OptimizeNotTrue := 1;
11288 OptimizeAllAnyOf := 1;
11289 ChangeChildrenOrder := 1;
11290
11291 BEGIN
11292
11293 --See if we want to generate gated combinations, yes by default.
11294
11295 SELECT DECODE(LOWER(value), '1', 1, 'on', 1, 'y', 1, 'yes', 1,'true', 1, 'enable', 1,
11296 '0', 0, 'off', 0, 'n', 0, 'no', 0,'false', 0, 'disable', 0,
11297 1) --default value
11298 INTO GenerateGatedCombo
11299 FROM cz_db_settings
11300 WHERE LOWER(setting_id) = GATED_COMBO_SETTING_ID
11301 AND LOWER(section_name) = DBSETTINGS_SECTION_NAME;
11302
11303 EXCEPTION
11304 WHEN OTHERS THEN
11305 GenerateGatedCombo := 1;
11306 END;
11307
11308 BEGIN
11309
11310 --See if we want to stop when a fatal rule error is encountered, yes by default.
11311
11312 SELECT DECODE(LOWER(value), '1', 1, 'on', 1, 'y', 1, 'yes', 1,'true', 1, 'enable', 1,
11313 '0', 0, 'off', 0, 'n', 0, 'no', 0,'false', 0, 'disable', 0,
11314 1) --default value
11315 INTO StopOnFatalRuleError
11316 FROM cz_db_settings
11317 WHERE LOWER(setting_id) = STOP_ON_ERROR_SETTING_ID
11318 AND LOWER(section_name) = DBSETTINGS_SECTION_NAME;
11319
11320 EXCEPTION
11321 WHEN OTHERS THEN
11322 StopOnFatalRuleError := 1;
11323 END;
11324
11325 BEGIN
11326
11327 --See if we want to generate logic only for updated models, yes by default.
11328
11329 SELECT DECODE(LOWER(value), '1', 1, 'on', 1, 'y', 1, 'yes', 1,'true', 1, 'enable', 1,
11330 '0', 0, 'off', 0, 'n', 0, 'no', 0,'false', 0, 'disable', 0,
11331 1) --default value
11332 INTO GenerateUpdatedOnly
11333 FROM cz_db_settings
11334 WHERE LOWER(setting_id) = UPDATED_ONLY_SETTING_ID
11335 AND LOWER(section_name) = DBSETTINGS_SECTION_NAME;
11336
11337 EXCEPTION
11338 WHEN OTHERS THEN
11339 GenerateUpdatedOnly := 1;
11340 END;
11341
11342 --Get the logic generation run id. If a valid value has been passed as a parameter, use it,
11343 --else generate a new value.
11344
11345 IF(thisRunId IS NULL OR thisRunId = 0)THEN
11346 SELECT cz_xfr_run_infos_s.NEXTVAL INTO thisRunId FROM DUAL;
11347 END IF;
11348
11349 --Read the cz_effectivity_sets table into memory and create hash tables for
11350 --effectivity dates
11351
11352 SELECT effectivity_set_id, effective_from, effective_until
11353 BULK COLLECT INTO gvSetId, gvEffFrom, gvEffUntil
11354 FROM cz_effectivity_sets
11355 WHERE deleted_flag = FLAG_NOT_DELETED;
11356
11357 --Add the indexing option
11358
11359 IF(gvSetId.LAST IS NOT NULL)THEN
11360 FOR i IN gvSetId.FIRST..gvSetId.LAST LOOP
11361 gvIndexBySetId(gvSetId(i)) := i;
11362 END LOOP;
11363 END IF;
11364
11365 --This block is introduced to implement locking.
11366
11367 BEGIN
11368
11369 l_locked_models.DELETE;
11370 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);
11371
11372 IF(l_lock_status <> FND_API.G_RET_STS_SUCCESS)THEN
11373 RAISE FAILED_TO_LOCK_MODEL;
11374 END IF;
11375
11376 --To disable this functionality, comment out the following IF block. Previously, we
11377 --could not correctly handle accumulators and NOTTRUE operator, for which we needed
11378 --to modify a child structure file even if it was up-to-date.
11379
11380 --Pre-populate the list of models that don't need to be regenerated because logic exists
11381 --and satisfies the 'up-to-date' criterion. Part of the fix for the bug #1941626.
11382 --For debugging purposes it may be convenient to be able to regenerate logic without any
11383 --dependency on the dates - the old way. A db setting is provided for that.
11384
11385 IF(GenerateUpdatedOnly = 1)THEN
11386
11387 --Have to always generate logic for the root model because the trigger updating
11388 --last_logic_update column is commented out on cz_expression_nodes, and this is
11389 --the only table Developer updates for some rule changes.
11390 --This is why we do not care about the return value and pass the margin reverse
11391 --dates.
11392
11393 nParam := CHECK_DATES(inDevlProjectId, EpochEndDate, EpochBeginDate);
11394 END IF;
11395
11396 globalLevel := globalLevel + 1;
11397 globalStack(globalLevel) := inDevlProjectId;
11398 globalRef(globalLevel) := inDevlProjectId;
11399 globalInstance(globalLevel) := 0;
11400
11401 --Start off the recursion
11402
11403 GENERATE_COMPONENT_TREE(inDevlProjectId, inDevlProjectId, NULL);
11404
11405 --LCE header maintainance
11406
11407 COMMIT_HEADERS;
11408
11409 EXCEPTION
11410 WHEN FAILED_TO_LOCK_MODEL THEN
11411
11412 FOR jmessage IN 1..l_msg_count LOOP
11413 REPORT(fnd_msg_pub.get(jmessage, FND_API.G_FALSE), 0);
11414 END LOOP;
11415
11416 ROLLBACK_HEADERS;
11417 WHEN OTHERS THEN
11418 RAISE;
11419 END;
11420
11421 --Handle here the exceptions that should terminate the logic tree generation process.
11422
11423 EXCEPTION
11424 WHEN CZ_S_UNABLE_TO_CREATE_HEADER THEN
11425 --'Unable to create logic header because of %ERRORTEXT'
11426 REPORT(CZ_UTILS.GET_TEXT('CZ_G_UNABLE_TO_CREATE_HEADER', 'ERRORTEXT', errorMessage), 0);
11427 ROLLBACK_HEADERS;
11428 WHEN CZ_R_UNABLE_TO_CREATE_HEADER THEN
11429 --'Unable to create logic header because of %ERRORTEXT'
11430 REPORT(CZ_UTILS.GET_TEXT('CZ_G_UNABLE_TO_CREATE_HEADER', 'ERRORTEXT', errorMessage), 0);
11431 ROLLBACK_HEADERS;
11432 WHEN CZ_S_DEADLOOP_DETECTED THEN
11433 REPORT(errorMessage, 0);
11434 ROLLBACK_HEADERS;
11435 WHEN CZ_S_UNKNOWN_FEATURE_TYPE THEN
11436 REPORT(errorMessage, 0);
11437 ROLLBACK_HEADERS;
11438 WHEN CZ_S_UNKNOWN_NODE_TYPE THEN
11439 REPORT(errorMessage, 0);
11440 ROLLBACK_HEADERS;
11441 WHEN CZ_S_UNKNOWN_BOM_NODE_TYPE THEN
11442 REPORT(errorMessage, 0);
11443 ROLLBACK_HEADERS;
11444 WHEN CZ_S_TOO_MANY_OPTIONS THEN
11445 REPORT(errorMessage, 0);
11446 ROLLBACK_HEADERS;
11447 WHEN CZ_S_WRONG_EFFECTIVITY_SET THEN
11448 REPORT(errorMessage, 0);
11449 ROLLBACK_HEADERS;
11450 WHEN CZ_S_INCONSISTENT_QUANTITY THEN
11451 REPORT(errorMessage, 0);
11452 ROLLBACK_HEADERS;
11453 WHEN CZ_S_INCORRECT_QUANTITY THEN
11454 --'BOM item ''%ITEMNAME'' cannot have default quantity greater than 1 because it contains other trackable BOM items.'
11455 REPORT(CZ_UTILS.GET_TEXT('CZ_S_INCORRECT_QUANTITY', 'ITEMNAME', glName(nParam)), 0);
11456 ROLLBACK_HEADERS;
11457 WHEN CZ_S_TRACKABLE_CHILDREN THEN
11458 --'Invalid Model structure: ''%CHILDNAME'' is a direct child of ''%MODELNAME''. A trackable BOM item cannot be a direct child of a Container Model.'
11459 REPORT(CZ_UTILS.GET_TEXT('CZ_S_TRACKABLE_CHILDREN', 'CHILDNAME', glName(nParam), 'MODELNAME', errorMessage), 0);
11460 ROLLBACK_HEADERS;
11461 WHEN CZ_S_TRACKABLE_STANDARD THEN
11462 --'Invalid Model structure: ''%CHILDNAME'' is a direct child of ''%MODELNAME''. A trackable Standard Item cannot be
11463 -- a direct child of a non-trackable ATO or PTO BOM Model that is referenced by a Container Model.'
11464 REPORT(CZ_UTILS.GET_TEXT('CZ_S_TRACKABLE_STANDARD', 'CHILDNAME', glName(nParam), 'MODELNAME', errorMessage), 0);
11465 ROLLBACK_HEADERS;
11466 WHEN CZ_S_MULTIPLE_TRACKABLE THEN
11467 --'Invalid Model structure: Multiple references exist to the trackable instance ''%CHILDNAME''.'
11468 REPORT(CZ_UTILS.GET_TEXT('CZ_S_MULTIPLE_TRACKABLE', 'CHILDNAME', errorMessage), 0);
11469 ROLLBACK_HEADERS;
11470 WHEN CZ_S_MULTIPLE_INSTANCES THEN
11471 --'Invalid Model structure: The non-trackable Model ''%MODELNAME'' cannot have multiple instances because it is not a descendent of a trackable Model and it
11472 -- contains the trackable Model ''%CHILDNAME''. Please set both the Instances Minimum and Maximum fields for ''%MODELNAME'' to 1.'
11473 REPORT(CZ_UTILS.GET_TEXT('CZ_S_MULTIPLE_INSTANCES', 'CHILDNAME', errorMessage, 'MODELNAME', glName(nParam)), 0);
11474 ROLLBACK_HEADERS;
11475 WHEN CZ_S_CONNECT_NONTRACKABLE THEN
11476 --'Invalid Connector: Connector to non-trackable Model ''%CHILDNAME'' from the trackable Model ''%MODELNAME''. A Connector from a non-trackable Model
11477 -- to a trackable Model is not allowed in a Container Model.'
11478 REPORT(CZ_UTILS.GET_TEXT('CZ_S_CONNECT_NONTRACKABLE', 'CHILDNAME', errorMessage, 'MODELNAME', glName(nParam)), 0);
11479 ROLLBACK_HEADERS;
11480 WHEN CZ_S_CONTAINER_REFERENCE THEN
11481 --'Invalid Reference: Model ''%MODELNAME'' references the Model ''%CHILDNAME''. A Container Model cannot reference another Container Model.'
11482 REPORT(CZ_UTILS.GET_TEXT('CZ_S_CONTAINER_REFERENCE', 'CHILDNAME', errorMessage, 'MODELNAME', rootProjectName), 0);
11483 ROLLBACK_HEADERS;
11484 WHEN CZ_S_CONNECTOR_TRACKABLE THEN
11485 --'The Connector from ''%MODELNAME'' to the trackable Model ''%CHILDNAME'' is not allowed because no ancestor of ''%MODELNAME'' is trackable.'
11486 REPORT(CZ_UTILS.GET_TEXT('CZ_S_CONNECTOR_TRACKABLE', 'CHILDNAME', glName(nParam), 'MODELNAME', errorMessage), 0);
11487 ROLLBACK_HEADERS;
11488 WHEN CZ_S_INCORRECT_CONTAINER THEN
11489 --'The Reference to trackable Model ''%CHILDNAME'' in the Container Model ''%MODELNAME'' has an invalid number
11490 -- of Instances specified. Please set Minimum Instances to 0 and Maximum Instances to Null for this node,
11491 -- then regenerate the Active Model.'
11492 REPORT(CZ_UTILS.GET_TEXT('CZ_S_INCORRECT_CONTAINER', 'CHILDNAME', errorMessage, 'MODELNAME', rootProjectName), 0);
11493 ROLLBACK_HEADERS;
11494 WHEN CZ_S_NO_TRACKABLE_FLAG THEN
11495 --'Trackable status is undefined for the Model ''%CHILDNAME'' in the Container Model ''%MODELNAME''.
11496 -- Please refresh the Model by running the Refresh a Single Configuration Model concurrent program
11497 -- and then regenerate the Active Model.'
11498 REPORT(CZ_UTILS.GET_TEXT('CZ_S_NO_TRACKABLE_FLAG', 'CHILDNAME', errorMessage, 'MODELNAME', rootProjectName), 0);
11499 ROLLBACK_HEADERS;
11500 WHEN CZ_S_NO_DATA_IN_PROJECT THEN
11501 --'Project ''%PROJECTNAME'' contains no data, no logic generated'
11502 REPORT(CZ_UTILS.GET_TEXT('CZ_S_NO_DATA_IN_PROJECT', 'PROJECTNAME', errorMessage), 0);
11503 ROLLBACK_HEADERS;
11504 WHEN CZ_S_NO_SUCH_PROJECT THEN
11505 --'Project does not exist for the specified ID: %PROJECTID. No logic generated.'
11506 REPORT(CZ_UTILS.GET_TEXT('CZ_S_NO_SUCH_PROJECT', 'PROJECTID', nParam), 0);
11507 ROLLBACK_HEADERS;
11508 WHEN CZ_S_TRACKABLE_CONTAINER THEN
11509 --'Error in Model ''%PROJECTNAME'': A trackable Model cannot be a Container Model.'
11510 REPORT(CZ_UTILS.GET_TEXT('CZ_S_TRACKABLE_CONTAINER', 'PROJECTNAME', errorMessage), 0);
11511 ROLLBACK_HEADERS;
11512 WHEN CZ_LCE_MODEL_OUTOFDATE THEN
11513 --'The BOM Model ''%MODELNAME'' is out of date. Please refresh the Model by running the Refresh a Single
11514 -- Configuration Model concurrent program and then regenerate the Active Model.'
11515 REPORT(CZ_UTILS.GET_TEXT('CZ_LCE_MODEL_OUTOFDATE', 'MODELNAME', errorMessage), 0);
11516 ROLLBACK_HEADERS;
11517 WHEN CZ_LCE_INCORRECT_BOM THEN
11518 --'Incorrect BOM Model or Option Class ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
11519 -- Only BOM Standard Items can be shippable and inventory transactable.'
11520 REPORT(CZ_UTILS.GET_TEXT('CZ_LCE_INCORRECT_BOM', 'NODENAME', thisName, 'PARENTNAME', parentName, 'MODELNAME', errorMessage), 0);
11521 ROLLBACK_HEADERS;
11522 WHEN CZ_LCE_INCORRECT_ITEM THEN
11523 --'Incorrect BOM Standard Item ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
11524 -- All shippable items should be inventory transactable and vice versa.'
11525 REPORT(CZ_UTILS.GET_TEXT('CZ_LCE_INCORRECT_ITEM', 'NODENAME', thisName, 'PARENTNAME', parentName, 'MODELNAME', errorMessage), 0);
11526 ROLLBACK_HEADERS;
11527 WHEN CZ_LCE_INCORRECT_TANGIBLE THEN
11528 --'Incorrect BOM Standard Item ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
11529 -- All shippable items should be trackable non-ATO standard items with maximum quantity 1.'
11530 REPORT(CZ_UTILS.GET_TEXT('CZ_LCE_INCORRECT_TANGIBLE', 'NODENAME', thisName, 'PARENTNAME', parentName, 'MODELNAME', errorMessage), 0);
11531 ROLLBACK_HEADERS;
11532 WHEN CZ_LCE_INCORRECT_SHIPPABLE THEN
11533 --'Incorrect BOM Standard Item ''%NODENAME'' with parent ''%PARENTNAME'' in BOM Model ''%MODELNAME''.
11534 -- All shippable items should be serializable trackable non-ATO standard items.'
11535 REPORT(CZ_UTILS.GET_TEXT('CZ_LCE_INCORRECT_SHIPPABLE', 'NODENAME', thisName, 'PARENTNAME', parentName, 'MODELNAME', errorMessage), 0);
11536 ROLLBACK_HEADERS;
11537 WHEN CZ_G_INVALID_RULE_EXPLOSION THEN
11538 --'Internal data error. Unable to continue because of invalid data in rule ''%RULENAME''. Disable or delete the rule to generate logic.'
11539 errorMessage := CZ_UTILS.GET_TEXT('CZ_G_INVALID_RULE_EXPLOSION', 'RULENAME', errorMessage);
11540 REPORT(errorMessage, 0);
11541 ROLLBACK_HEADERS;
11542 WHEN CZ_G_INVALID_MODEL_EXPLOSION THEN
11543 --'Internal data error. Unable to continue because of invalid data in model ''%MODELNAME'' - loop detected.'
11544 errorMessage := CZ_UTILS.GET_TEXT('CZ_G_INVALID_MODEL_EXPLOSION', 'MODELNAME', errorMessage);
11545 REPORT(errorMessage, 0);
11546 ROLLBACK_HEADERS;
11547 WHEN CZ_G_INVALID_EXPLOSION_TYPE THEN
11548 --'Internal data error. Unable to continue because of invalid data in the model ''%MODELNAME'' - incorrect explosion type.'
11549 errorMessage := CZ_UTILS.GET_TEXT('CZ_G_INVALID_EXPLOSION_TYPE', 'MODELNAME', errorMessage);
11550 REPORT(errorMessage, 0);
11551 ROLLBACK_HEADERS;
11552 WHEN OTHERS THEN
11553 IF(nDebug = 1 OR (nDebug >= 1000001 AND nDebug <= 1000011))THEN
11554 --'Unable to continue because of %ERRORTEXT. Reference explosions table may not be populated properly for model ''%MODELNAME'''
11555 errorMessage := CZ_UTILS.GET_TEXT('CZ_G_ERROR_IN_EXPLOSION', 'ERRORTEXT', SQLERRM, 'MODELNAME', glName(glIndexByPsNodeId(inDevlProjectId)));
11556 ELSIF(nDebug >= 40 AND nDebug <= 54)THEN
11557 --'Internal data error. Unable to continue because of invalid data in rule ''%RULENAME''. Disable or delete the rule to generate logic.'
11558 errorMessage := CZ_UTILS.GET_TEXT('CZ_G_INVALID_RULE_EXPLOSION', 'RULENAME', errorMessage);
11559 ELSIF(SUBSTR(TO_CHAR(nDebug), 1, 1) = '8')THEN
11560 --'Unable to continue because of %ERRORTEXT: (nRuleId)'
11561 errorMessage := CZ_UTILS.GET_TEXT('CZ_G_GENERAL_ERROR', 'ERRORTEXT', SQLERRM || ': (' || errorMessage || ')');
11562 ELSE
11563 --'Unable to continue because of %ERRORTEXT'
11564 errorMessage := CZ_UTILS.GET_TEXT('CZ_G_GENERAL_ERROR', 'ERRORTEXT', SQLERRM);
11565 END IF;
11566 REPORT(errorMessage, 0);
11567 ROLLBACK_HEADERS;
11568 END;
11569
11570 --Bug #4587682. Restore the session's nls numeric characters.
11571
11572 SET_NLS_CHARACTERS(StoreNlsCharacters);
11573
11574 EXCEPTION
11575 WHEN OTHERS THEN
11576 SET_NLS_CHARACTERS(StoreNlsCharacters);
11577 RAISE;
11578 END; --GENERATE_MODEL_TREE
11579 ---------------------------------------------------------------------------------------
11580 --An additional entry point for those callers who cannot handle defaulted parameters---
11581
11582 PROCEDURE GENERATE_LOGIC(inDevlProjectId IN NUMBER,
11583 thisRunId IN OUT NOCOPY NUMBER)
11584 IS
11585
11586 l_config_engine_type cz_devl_projects.config_engine_type%TYPE;
11587 l_fusion_debug VARCHAR2(240);
11588
11589 BEGIN
11590
11591 BEGIN
11592
11593 SELECT config_engine_type INTO l_config_engine_type
11594 FROM cz_devl_projects
11595 WHERE deleted_flag = FLAG_NOT_DELETED
11596 AND devl_project_id = inDevlProjectId;
11597
11598 EXCEPTION
11599 WHEN NO_DATA_FOUND THEN
11600 l_config_engine_type := 'L';
11601 END;
11602
11603 IF ( l_config_engine_type = 'F') THEN
11604
11605 l_fusion_debug := NVL ( fnd_profile.value_wnps ('CZ_DEV_FCE_DEBUG_LOGIC'), 'N');
11606
11607 IF ( l_fusion_debug = 'N' ) THEN
11608
11609 cz_fce_compile.compile_logic ( inDevlProjectId, thisRunId );
11610
11611 ELSE
11612
11613 cz_fce_compile.debug_logic ( inDevlProjectId, thisRunId );
11614
11615 END IF;
11616
11617 ELSE
11618
11619 GENERATE_LOGIC_(inDevlProjectId, thisRunId, 0);
11620
11621 END IF;
11622 END;
11623 ---------------------------------------------------------------------------------------
11624 --This entry makes the logic generation work remotely in a distributed transaction,even
11625 --if the model contains property-based compatibility rules - bug #2028790.
11626 --DDL used in the property-based compatibility rules makes implicit commits and commits
11627 --are not allowed in a distributed transaction when the remote procedure has parameters
11628 --of type OUT.
11629
11630 PROCEDURE GENERATE_LOGIC__(inDevlProjectId IN NUMBER,
11631 thisRunId IN NUMBER)
11632 IS
11633 outRunId NUMBER := thisRunId;
11634 BEGIN
11635 GENERATE_LOGIC_(inDevlProjectId, outRunId, 1);
11636 END;
11637 ---------------------------------------------------------------------------------------
11638 BEGIN
11639
11640 OperatorLiterals(OPERATOR_ADD) := ' + ';
11641 OperatorLiterals(OPERATOR_SUB) := ' - ';
11642 OperatorLiterals(OPERATOR_MULT) := ' * ';
11643 OperatorLiterals(OPERATOR_DIV) := ' / ';
11644 OperatorLiterals(OPERATOR_EQUALS) := ' = ';
11645 OperatorLiterals(OPERATOR_NOTEQUALS) := ' != ';
11646 OperatorLiterals(OPERATOR_GT) := ' > ';
11647 OperatorLiterals(OPERATOR_LT) := ' < ';
11648 OperatorLiterals(OPERATOR_GE) := ' >= ';
11649 OperatorLiterals(OPERATOR_LE) := ' <= ';
11650 OperatorLiterals(OPERATOR_ADD_INT) := ' + ';
11651 OperatorLiterals(OPERATOR_SUB_INT) := ' - ';
11652 OperatorLiterals(OPERATOR_MULT_INT) := ' * ';
11653 OperatorLiterals(OPERATOR_EQUALS_INT) := ' = ';
11654 OperatorLiterals(OPERATOR_NOTEQUALS_INT) := ' != ';
11655 OperatorLiterals(OPERATOR_GT_INT) := ' > ';
11656 OperatorLiterals(OPERATOR_LT_INT) := ' < ';
11657 OperatorLiterals(OPERATOR_GE_INT) := ' >= ';
11658 OperatorLiterals(OPERATOR_LE_INT) := ' <= ';
11659 OperatorLiterals(OPERATOR_POW_INT) := ' POW ';
11660 OperatorLiterals(OPERATOR_ROUND) := ' ROUND ';
11661 OperatorLiterals(OPERATOR_CEILING) := ' CEILING ';
11662 OperatorLiterals(OPERATOR_FLOOR) := ' FLOOR ';
11663 OperatorLiterals(OPERATOR_TRUNCATE) := ' TRUNCATE ';
11664 OperatorLiterals(OPERATOR_MIN) := ' MIN ';
11665 OperatorLiterals(OPERATOR_MAX) := ' MAX ';
11666 OperatorLiterals(OPERATOR_AND) := ' AND ';
11667 OperatorLiterals(OPERATOR_OR) := ' OR ';
11668 OperatorLiterals(OPERATOR_NOT) := ' NOT ';
11669 OperatorLiterals(OPERATOR_NOTTRUE) := ' NOTTRUE ';
11670 OperatorLiterals(OPERATOR_COS) := ' COS ';
11671 OperatorLiterals(OPERATOR_ACOS) := ' ACOS ';
11672 OperatorLiterals(OPERATOR_COSH) := ' COSH ';
11673 OperatorLiterals(OPERATOR_SIN) := ' SIN ';
11674 OperatorLiterals(OPERATOR_ASIN) := ' ASIN ';
11675 OperatorLiterals(OPERATOR_SINH) := ' SINH ';
11676 OperatorLiterals(OPERATOR_TAN) := ' TAN ';
11677 OperatorLiterals(OPERATOR_ATAN) := ' ATAN ';
11678 OperatorLiterals(OPERATOR_TANH) := ' TANH ';
11679 OperatorLiterals(OPERATOR_LOG) := ' LOG ';
11680 OperatorLiterals(OPERATOR_LOG10) := ' LOG10 ';
11681 OperatorLiterals(OPERATOR_EXP) := ' EXP ';
11682 OperatorLiterals(OPERATOR_ABS) := ' ABS ';
11683 OperatorLiterals(OPERATOR_SQRT) := ' SQRT ';
11684 OperatorLiterals(OPERATOR_MATHDIV) := ' DIV ';
11685 OperatorLiterals(OPERATOR_POW) := ' POW ';
11686 OperatorLiterals(OPERATOR_ATAN2) := ' ATAN2 ';
11687 OperatorLiterals(OPERATOR_MOD) := ' MOD ';
11688 OperatorLiterals(OPERATOR_ROUNDTONEAREST) := ' ROUND ';
11689 OperatorLiterals(OPERATOR_ROUNDUPTONEAREST) := ' CEILING ';
11690 OperatorLiterals(OPERATOR_ROUNDDOWNTONEAREST) := ' FLOOR ';
11691 OperatorLiterals(OPERATOR_ALLOF) := ' All True ';
11692 OperatorLiterals(OPERATOR_ANYOF) := ' Any True ';
11693 OperatorLiterals(OPERATOR_NONE) := ' ';
11694
11695 OperatorLetters(OPERATOR_AND) := ' L ';
11696 OperatorLetters(OPERATOR_OR) := ' N ';
11697 OperatorLetters(OPERATOR_ALLOF) := ' L ';
11698 OperatorLetters(OPERATOR_ANYOF) := ' N ';
11699 OperatorLetters(RULE_OPERATOR_REQUIRES) := ' R ';
11700 OperatorLetters(RULE_OPERATOR_IMPLIES) := ' I ';
11701 OperatorLetters(RULE_OPERATOR_EXCLUDES) := ' E ';
11702 OperatorLetters(RULE_OPERATOR_NEGATES) := ' N ';
11703
11704 CodeByCodeLookup(TEMPLATE_ANYTRUE) := OPERATOR_ANYOF;
11705 CodeByCodeLookup(TEMPLATE_ALLTRUE) := OPERATOR_ALLOF;
11706 END;