DBA Data[Home] [Help]

PACKAGE BODY: APPS.BSC_AW_BSC_METADATA

Source


1 package body BSC_AW_BSC_METADATA AS
2 /*$Header: BSCAWMDB.pls 120.16 2006/04/20 11:31 vsurendr noship $*/
3 
4 procedure get_all_parent_child(
5 p_dim_level_list dbms_sql.varchar2_table,
6 p_dim_parent_child out nocopy BSC_AW_ADAPTER_DIM.dim_parent_child_tb,
7 p_dim_levels out nocopy BSC_AW_ADAPTER_DIM.levels_tv
8 ) is
9 --
10 l_level_considered dbms_sql.varchar2_table;
11 --
12 Begin
13   p_dim_parent_child.delete;
14   l_level_considered.delete;
15   p_dim_levels.delete;
16   g_count:=0;--to test infinite recursion
17   for i in 1..p_dim_level_list.count loop
18     if not bsc_aw_utility.in_array(l_level_considered,p_dim_level_list(i)) then
19       get_parent_children(p_dim_level_list(i),l_level_considered,p_dim_parent_child);
20     end if;
21   end loop;
22   --get the level info
23   get_all_distinct_levels(l_level_considered,p_dim_levels);
24 Exception when others then
25   log_n('Exception in get_all_parent_child '||sqlerrm);
26   raise;
27 End;
28 
29 procedure get_parent_children(
30 p_level varchar2,
31 p_level_considered in out nocopy dbms_sql.varchar2_table,
32 p_dim_parent_child in out nocopy BSC_AW_ADAPTER_DIM.dim_parent_child_tb
33 ) is
34 --
35 l_parents BSC_AW_ADAPTER_DIM.dim_parent_child_tb;
36 l_children BSC_AW_ADAPTER_DIM.dim_parent_child_tb;
37 --
38 l_count number;
39 --
40 Begin
41   --p_level is the start level.
42   if p_level is null then
43     return;
44   end if;
45   g_count:=g_count+1;
46   if g_count>100000 then
47     log_n('Infinite loop detected in get_parent_children');
48     raise g_exception;
49   end if;
50   if bsc_aw_utility.in_array(p_level_considered,p_level) then
51     return;
52   end if;
53   p_level_considered(p_level_considered.count+1):=p_level;
54   l_parents.delete;
55   l_children.delete;
56   bsc_metadata.get_parent_level(p_level,l_parents);
57   bsc_metadata.get_child_level(p_level,l_children);
58   --assume that a parent child pair exists as a unique row in bsc_sys_dim_level_rels
59   l_count:=p_dim_parent_child.count;
60   --have to handle single level RECURSIVE dimensions. rec dim must have single entry with parent=child
61   if l_parents.count=0 then --this is single level dim or top level
62     l_count:=l_count+1;
63     p_dim_parent_child(l_count).parent_level:=null;
64     p_dim_parent_child(l_count).child_level:=p_level;
65   else
66     for i in 1..l_parents.count loop
67       l_count:=l_count+1;
68       --l_parents(i) has the parent level, child level, child fk and parent pk
69       p_dim_parent_child(l_count):=l_parents(i);
70     end loop;
71   end if;
72   --for each child / parent, call this recursively. do this only for non rec dim
73   if l_parents.count=1 and l_parents(1).parent_level=l_parents(1).child_level then
74     --this is rec dim
75     null;
76   else
77     --lets assume that there is no circular relation. otherwise, this can get into infinite recursion
78     for i in 1..l_parents.count loop
79       get_parent_children(l_parents(i).parent_level,p_level_considered,p_dim_parent_child);
80     end loop;
81     for i in 1..l_children.count loop
82       get_parent_children(l_children(i).child_level,p_level_considered,p_dim_parent_child);
83     end loop;
84   end if;
85 Exception when others then
86   log_n('Exception in get_parent_children '||sqlerrm);
87   raise;
88 End;
89 
90 procedure get_parent_level(p_level varchar2,p_parents out nocopy dbms_sql.varchar2_table) is
91 l_parents BSC_AW_ADAPTER_DIM.dim_parent_child_tb;
92 Begin
93   bsc_metadata.get_parent_level(p_level,l_parents);
94   for i in 1..l_parents.count loop
95     if l_parents(i).parent_level is not null then
96       p_parents(p_parents.count+1):=l_parents(i).parent_level;
97     end if;
98   end loop;
99 Exception when others then
100   log_n('Exception in get_parent_level '||sqlerrm);
101   raise;
102 End;
103 
104 procedure get_child_level(p_level varchar2,p_children out nocopy dbms_sql.varchar2_table) is
105 l_children BSC_AW_ADAPTER_DIM.dim_parent_child_tb;
106 Begin
107   bsc_metadata.get_child_level(p_level,l_children);
108   for i in 1..l_children.count loop
109     if l_children(i).child_level is not null then
110       p_children(p_children.count+1):=l_children(i).child_level;
111     end if;
112   end loop;
113 Exception when others then
114   log_n('Exception in get_child_level '||sqlerrm);
115   raise;
116 End;
117 
118 /*
119 position is not set here. its set in the dim adapter
120 */
121 procedure get_all_distinct_levels(
122 p_levels dbms_sql.varchar2_table,
123 p_dim_levels out nocopy BSC_AW_ADAPTER_DIM.levels_tv
124 ) is
125 --
126 l_level_id number;
127 l_level_pk varchar2(100);
128 l_level_pk_datatype varchar2(100);
129 l_level_source varchar2(100);
130 --
131 Begin
132   if g_debug then
133     log_n('In get_all_distinct_levels '||p_levels.count);
134   end if;
135   p_dim_levels.delete;
136   for i in 1..p_levels.count loop
137     --l_level_id: can this be null?
138     log_n(p_levels(i));
139     bsc_metadata.get_level_pk(p_levels(i),l_level_id,l_level_pk,l_level_pk_datatype,l_level_source);
140     p_dim_levels(p_levels(i)).level_name:=p_levels(i);
141     p_dim_levels(p_levels(i)).level_id:=l_level_id;
142     p_dim_levels(p_levels(i)).pk.pk:=l_level_pk;
143     p_dim_levels(p_levels(i)).pk.data_type:=l_level_pk_datatype;
144     p_dim_levels(p_levels(i)).level_source:=l_level_source;
145   end loop;
146 Exception when others then
147   log_n('Exception in get_all_distinct_levels '||sqlerrm);
148   raise;
149 End;
150 
151 /*
152 we need to get the levels of the dim, then pass the levels to get the kpi involved
153 returns a kpi if a kpi has any of the levels as its dim. we also return the dim set
154 in which the dim levels are involved
155 */
156 procedure get_kpi_for_dim(
157 p_dim in out nocopy bsc_aw_adapter_dim.dimension_r
158 ) is
159 --
160 l_kpi dbms_sql.varchar2_table;
161 l_dimset dbms_sql.varchar2_table;
162 l_kpi_flag boolean;
163 l_dimset_flag boolean;
164 l_kpi_index number;
165 --
166 Begin
167   for i in 1..p_dim.level_groups.count loop
168     for j in 1..p_dim.level_groups(i).levels.count loop
169       --NOTE!!! if a dim is std, then all kpi implemented in aw have this dim
170       if p_dim.dim_type='std' then
171         get_all_kpi_in_aw(l_kpi,l_dimset);
172       else
173         bsc_metadata.get_kpi_for_dim(p_dim.level_groups(i).levels(j).level_name,l_kpi,l_dimset);
174       end if;
175       --if both kpi+dimset already exists, do not add it. else add it.
176       for k in 1..l_kpi.count loop
177         l_kpi_flag:=false;
178         l_dimset_flag:=false;
179         l_kpi_index:=0;
180         for m in 1..p_dim.kpi_for_dim.count loop
181           if p_dim.kpi_for_dim(m).kpi=l_kpi(k) then
182             l_kpi_flag:=true;
183             l_kpi_index:=m;
184             --does the dimset also exist?
185             for n in 1..p_dim.kpi_for_dim(m).dim_set.count loop
186               if p_dim.kpi_for_dim(m).dim_set(n)=l_dimset(k) then
187                 l_dimset_flag:=true;
188                 exit;
189               end if;
190             end loop;
191             exit;
192           end if;
193         end loop;
194         if l_kpi_flag and l_dimset_flag=false then
195           p_dim.kpi_for_dim(l_kpi_index).dim_set(p_dim.kpi_for_dim(l_kpi_index).dim_set.count+1):=l_dimset(k);
196         elsif l_kpi_flag=false and l_dimset_flag=false then
197           p_dim.kpi_for_dim(p_dim.kpi_for_dim.count+1).kpi:=l_kpi(k);
198           p_dim.kpi_for_dim(p_dim.kpi_for_dim.count).dim_set(p_dim.kpi_for_dim(p_dim.kpi_for_dim.count).dim_set.count+1):=l_dimset(k);
199         end if;
200       end loop;
201     end loop;
202   end loop;
203 Exception when others then
204   log_n('Exception in get_kpi_for_dim '||sqlerrm);
205   raise;
206 End;
207 
208 --given a list of kpi, get the list of all dim levels that are referenced by the kpi
209 procedure get_dims_for_kpis(
210 p_kpi_list dbms_sql.varchar2_table,
211 p_dim_list out nocopy dbms_sql.varchar2_table
212 ) is
213 Begin
214   bsc_metadata.get_dims_for_kpis(p_kpi_list,p_dim_list);
215 Exception when others then
216   log_n('Exception in get_dims_for_kpis '||sqlerrm);
217   raise;
218 End;
219 
220 /*
221 for DBI rec dim. we will have to get the info we need from static package or optimizer std output.
222 for any dim, there can be only 1 data source for all the levels. if there are 2 levels, then the data
223 source will be like
224 (select level1, level2 from ...)
225 */
226 procedure create_rec_data_source(
227 p_dimension in out nocopy bsc_aw_adapter_dim.dimension_r
228 ) is
229 Begin
230   create_data_source(p_dimension);
231   --if rec dim, also set the denorm data source
232   --rec dim have only 1 level
233   if p_dimension.recursive='Y' then
234     bsc_metadata.get_denorm_data_source(
235     p_dimension.level_groups(1).levels(1).level_name,
236     p_dimension.level_groups(1).data_source.child_col,
237     p_dimension.level_groups(1).data_source.parent_col,
238     p_dimension.level_groups(1).data_source.position_col,
239     p_dimension.level_groups(1).data_source.denorm_data_source,
240     p_dimension.level_groups(1).data_source.denorm_change_data_source);
241   end if;
242 Exception when others then
243   log_n('Exception in create_rec_data_source '||sqlerrm);
244   raise;
245 End;
246 
247 /*
248 This procedure creates the data source for non rec dbi dimensions
249 */
250 procedure create_data_source(
251 p_dimension in out nocopy bsc_aw_adapter_dim.dimension_r
252 ) is
253 l_level_list dbms_sql.varchar2_table;
254 l_level_pk_col dbms_sql.varchar2_table;
255 Begin
256   for i in 1..p_dimension.level_groups(1).levels.count loop
257     l_level_list(i):=p_dimension.level_groups(1).levels(i).level_name;
258   end loop;
259   bsc_metadata.get_dim_data_source(l_level_list,l_level_pk_col,
260   p_dimension.level_groups(1).data_source.data_source,p_dimension.level_groups(1).data_source.inc_data_source);
261   --for bsc dimensions, p_dimension.level_groups(1).data_source.data_source will be null
262   --it will be non null only foR DBI dimensions
263   if p_dimension.level_groups(1).data_source.data_source is not null then
264     for i in 1..p_dimension.level_groups(1).levels.count loop
265       p_dimension.level_groups(1).data_source.dim_name(i):=p_dimension.level_groups(1).levels(i).level_name;
266       p_dimension.level_groups(1).data_source.pk_col(i):=l_level_pk_col(i);
267     end loop;
268   end if;
269 Exception when others then
270   log_n('Exception in create_data_source '||sqlerrm);
271   raise;
272 End;
273 
274 procedure set_dim_recursive(p_dimension in out nocopy bsc_aw_adapter_dim.dimension_r) is
275 Begin
276   --in rec dim, there is only 1 level
277   p_dimension.recursive:=bsc_metadata.is_dim_recursive(p_dimension.level_groups(1).levels(1).level_name);
278   if p_dimension.recursive='Y' then
279     p_dimension.recursive_norm_hier:='Y'; --implement rec dim as normal by default
280   end if;
281 Exception when others then
282   log_n('Exception in set_dim_recursive '||sqlerrm);
283   raise;
284 End;
285 
286 procedure get_kpi_for_calendar(p_calendar in out nocopy bsc_aw_calendar.calendar_r) is
287 l_kpi_list dbms_sql.varchar2_table;
288 Begin
289   bsc_metadata.get_kpi_for_calendar(p_calendar.calendar_id,l_kpi_list);
290   for i in 1..l_kpi_list.count loop
291     p_calendar.kpi_for_dim(i).kpi:=l_kpi_list(i);
292   end loop;
293 Exception when others then
294   log_n('Exception in get_kpi_for_calendar '||sqlerrm);
295   raise;
296 End;
297 
298 /*
299 gets
300 calendar kpi belongs to
301 */
302 procedure get_kpi_properties(p_kpi in out nocopy bsc_aw_adapter_kpi.kpi_r) is
303 l_calendar number;
304 Begin
305   bsc_metadata.get_kpi_calendar(p_kpi.kpi,l_calendar);
306   p_kpi.calendar:=l_calendar;
307 Exception when others then
308   log_n('Exception in get_kpi_properties '||sqlerrm);
309   raise;
310 End;
311 
312 /*
313 given a kpi find out
314 1. dim sets
315 */
316 procedure get_kpi_dim_sets(p_kpi in out nocopy bsc_aw_adapter_kpi.kpi_r) is
317 l_dim_set dbms_sql.varchar2_table;
318 Begin
319   bsc_metadata.get_kpi_dim_sets(p_kpi.kpi,l_dim_set);
320   --l_dim_set will be numbers like 1,2 etc to make the name unique, append with kpi
321   for i in 1..l_dim_set.count loop
322     p_kpi.dim_set(i).dim_set:=l_dim_set(i);
323     p_kpi.dim_set(i).dim_set_name:='dimset_'||l_dim_set(i)||'_'||p_kpi.kpi;
324   end loop;
325 Exception when others then
326   log_n('Exception in get_kpi_dim_sets '||sqlerrm);
327   raise;
328 End;
329 
330 /*
331 a dim set will have dim levels from diff dimensions. it can have city,state,product,prod category and customer
332 the info that city and state belong to geog dim is in bsc olap objects. this package does not access bsc_olap_objects
333 its a one way access to bsc metadata. so this procedure returns the list of dim levels to kpi adapter. the kpi adapter
334 will access bsc olap metadata to group these dim levels into Concat dims
335 */
336 procedure get_dim_set_dims(
337 p_kpi varchar2,
338 p_dim_set varchar2,
339 p_dim_level out nocopy dbms_sql.varchar2_table,
340 p_mo_dim_group out nocopy dbms_sql.varchar2_table,
341 p_skip_level out nocopy dbms_sql.varchar2_table
342 ) is
343 Begin
344   bsc_metadata.get_dim_set_dims(p_kpi,p_dim_set,p_dim_level,p_mo_dim_group,p_skip_level);
345 Exception when others then
346   log_n('Exception in get_dim_set_dims '||sqlerrm);
347   raise;
348 End;
349 
350 /*
351 given a dim set, find out all info about the measures
352 unlike get_dim_set_dims, we directly set the dim_set data structure with the measure properties
353 measures belong to kpi and dim sets within the kpi
354 */
355 procedure get_dim_set_measures(
356 p_kpi varchar2,
357 p_dim_set varchar2,
358 p_measure in out nocopy bsc_aw_adapter_kpi.measure_tb
359 ) is
360 l_measure dbms_sql.varchar2_table;
361 l_measure_type dbms_sql.varchar2_table;
362 l_data_type dbms_sql.varchar2_table;
363 l_agg_formula dbms_sql.varchar2_table;
364 l_projection dbms_sql.varchar2_table;
365 l_property dbms_sql.varchar2_table;
366 Begin
367   p_measure.delete;
368   bsc_metadata.get_dim_set_measures(p_kpi,p_dim_set,l_measure,l_measure_type,l_data_type,l_agg_formula,l_projection,l_property);
369   for i in 1..l_measure.count loop
370     p_measure(i).measure:=l_measure(i);
371     p_measure(i).measure_type:=l_measure_type(i);
372     p_measure(i).data_type:=l_data_type(i);
373     p_measure(i).agg_formula.agg_formula:=l_agg_formula(i);
374     p_measure(i).agg_formula.sql_agg_formula:=l_agg_formula(i);
375     if upper(p_measure(i).agg_formula.sql_agg_formula)='AVERAGE' then /*database avg function is AVG */
376       p_measure(i).agg_formula.sql_agg_formula:='AVG';
377     end if;
378     p_measure(i).agg_formula.std_aggregation:=bsc_aw_utility.is_std_aggregation_function(l_agg_formula(i));--Y N
379     p_measure(i).agg_formula.avg_aggregation:=bsc_aw_utility.is_avg_aggregation_function(l_agg_formula(i));--Y N
380     p_measure(i).sql_aggregated:='N';/*default */
381     p_measure(i).forecast:=l_projection(i);
382     p_measure(i).forecast_method:=null;--for now, we dont implement projection in aw
383     bsc_aw_utility.merge_property(p_measure(i).property,l_property(i),',');/*if BALANCE LAST VALUE, this can contain balance loaded Y/N column name */
384   end loop;
385 Exception when others then
386   log_n('Exception in get_dim_set_measures '||sqlerrm);
387   raise;
388 End;
389 
390 /*
391 given a dimset, get all the S views and their properties
392 gets both ZMV and regular MV
393 */
394 procedure get_s_views(p_kpi varchar2,p_dim_set in out nocopy bsc_aw_adapter_kpi.dim_set_r) is
395 l_s_views dbms_sql.varchar2_table;
396 l_levels dbms_sql.varchar2_table;
397 l_sview_level bsc_aw_adapter_kpi.level_r;
398 Begin
399   --get_s_views will return only regular MV not ZMV
400   bsc_metadata.get_s_views(p_kpi,p_dim_set.dim_set,l_s_views);
401   --for each s view get the level info
402   for i in 1..l_s_views.count loop
403     l_levels.delete;
404     bsc_metadata.get_s_view_levels(l_s_views(i),l_levels);
405     p_dim_set.s_view(p_dim_set.s_view.count+1).s_view:=l_s_views(i);
406     p_dim_set.s_view(p_dim_set.s_view.count).id:='MV_'||i;
407     for j in 1..l_levels.count loop
408       --note>>>a level can be in 1 dim only, even in the case of standalone levels
409       p_dim_set.s_view(p_dim_set.s_view.count).dim(j):=bsc_aw_adapter_kpi.get_kpi_level_dim_r(p_dim_set,l_levels(j));
410       l_sview_level:=bsc_aw_adapter_kpi.get_dim_level_r(p_dim_set.s_view(p_dim_set.s_view.count).dim(j),l_levels(j));
411       p_dim_set.s_view(p_dim_set.s_view.count).dim(j).levels.delete; --only hold the s view level info
412       p_dim_set.s_view(p_dim_set.s_view.count).dim(j).levels(1):=l_sview_level;
413     end loop;
414   end loop;
415   --get the ZMV
416   l_s_views.delete;
417   bsc_metadata.get_z_s_views(p_kpi,p_dim_set.dim_set,l_s_views);
418   for i in 1..l_s_views.count loop
419     l_levels.delete;
420     bsc_metadata.get_s_view_levels(l_s_views(i),l_levels);
421     p_dim_set.z_s_view(p_dim_set.z_s_view.count+1).s_view:=l_s_views(i);
422     p_dim_set.z_s_view(p_dim_set.z_s_view.count).id:='ZMV_'||i;
423     for j in 1..l_levels.count loop
424       p_dim_set.z_s_view(p_dim_set.z_s_view.count).dim(j):=bsc_aw_adapter_kpi.get_kpi_level_dim_r(p_dim_set,l_levels(j));
425       l_sview_level:=bsc_aw_adapter_kpi.get_dim_level_r(p_dim_set.z_s_view(p_dim_set.z_s_view.count).dim(j),l_levels(j));
426       p_dim_set.z_s_view(p_dim_set.z_s_view.count).dim(j).levels.delete;
427       p_dim_set.z_s_view(p_dim_set.z_s_view.count).dim(j).levels(1):=l_sview_level;
428     end loop;
429   end loop;
430 Exception when others then
431   log_n('Exception in get_s_views '||sqlerrm);
432   raise;
433 End;
434 
435 function is_target_at_higher_level(p_kpi varchar2,p_dim_set varchar2) return varchar2 is
436 Begin
437   return bsc_metadata.is_target_at_higher_level(p_kpi,p_dim_set);
438 Exception when others then
439   log_n('Exception in is_target_at_higher_level '||sqlerrm);
440   raise;
441 End;
442 
443 --this api called only when there are targets at higher levels
444 procedure get_target_dim_levels(p_kpi varchar2,p_target_dim_set in out nocopy bsc_aw_adapter_kpi.dim_set_r) is
445 l_levels dbms_sql.varchar2_table;
446 l_dim bsc_aw_adapter_kpi.dim_tb;--just temp backup
447 Begin
448   --backup dim and level info
449   l_dim:=p_target_dim_set.dim;
450   --delete all level info
451   for i in 1..p_target_dim_set.dim.count loop
452     p_target_dim_set.dim(i).levels.delete;
453   end loop;
454   bsc_metadata.get_target_levels(p_kpi,p_target_dim_set.dim_set,l_levels);
455   --now for these levels, fill in the dim info
456   for i in 1..l_dim.count loop
457     for j in 1..l_dim(i).levels.count loop
458       if bsc_aw_utility.in_array(l_levels,l_dim(i).levels(j).level_name) then
459         p_target_dim_set.dim(i).levels(p_target_dim_set.dim(i).levels.count+1):=l_dim(i).levels(j);
460       end if;
461     end loop;
462   end loop;
463   --get the filter at the lowest level for the target
464   --levels(1) is the lowest level of the target
465   for i in 1..p_target_dim_set.dim.count loop
466     get_dim_level_filter(p_kpi,p_target_dim_set.dim(i).levels(1));
467   end loop;
468 Exception when others then
469   log_n('Exception in get_target_dim_levels '||sqlerrm);
470   raise;
471 End;
472 
473 procedure get_target_dim_periodicity(p_kpi varchar2,p_target_dim_set in out nocopy bsc_aw_adapter_kpi.dim_set_r) is
474 --
475 l_periodicities dbms_sql.number_table;
476 l_calendar bsc_aw_adapter_kpi.calendar_r;
477 Begin
478   --backup
479   l_calendar:=p_target_dim_set.calendar;
480   p_target_dim_set.calendar.periodicity.delete;
481   --bsc_metadata.get_target_periodicity will only return lowest periodicity for targets
482   bsc_metadata.get_target_periodicity(p_kpi,p_target_dim_set.dim_set,l_periodicities);
483   for i in 1..l_calendar.periodicity.count loop
484     if bsc_aw_utility.in_array(l_periodicities,l_calendar.periodicity(i).periodicity) then
485       p_target_dim_set.calendar.periodicity(p_target_dim_set.calendar.periodicity.count+1):=l_calendar.periodicity(i);
486       p_target_dim_set.calendar.periodicity(p_target_dim_set.calendar.periodicity.count).lowest_level:='Y'; --these are lowest level for targets
487     end if;
488   end loop;
489   --NOTE!! the periodicity we have added for targets is the lowest periodicity only. we have to add the upper periodicities
490   --l_calendar has the parent child relations in it
491   for i in 1..p_target_dim_set.calendar.periodicity.count loop
492     fill_in_target_periodicity(p_target_dim_set.calendar,l_calendar,p_target_dim_set.calendar.periodicity(i).aw_dim);
493   end loop;
494 Exception when others then
495   log_n('Exception in get_target_dim_periodicity '||sqlerrm);
496   raise;
497 End;
498 
499 /*
500 fill in higher periodicities for targets
501 */
502 procedure fill_in_target_periodicity(
503 p_target_calendar in out nocopy bsc_aw_adapter_kpi.calendar_r,
504 p_source_calendar bsc_aw_adapter_kpi.calendar_r,
505 p_periodicity varchar2
506 ) is
507 --
508 l_flag boolean;
509 l_periodicity bsc_aw_adapter_kpi.periodicity_r;
510 Begin
511   if p_periodicity is not null then
512     l_flag:=false;
513     for i in 1..p_target_calendar.periodicity.count loop
514       if p_target_calendar.periodicity(i).aw_dim=p_periodicity then
515         l_flag:=true;
516       end if;
517     end loop;
518     if l_flag=false then
519       p_target_calendar.periodicity(p_target_calendar.periodicity.count+1):=bsc_aw_adapter_kpi.get_periodicity_r(p_source_calendar.periodicity,
520       p_periodicity);
521     end if;
522     for i in 1..p_source_calendar.parent_child.count loop
523       if p_source_calendar.parent_child(i).child_dim_name=p_periodicity then
524       --and p_source_calendar.parent_child(i).parent_dim_name is not null then
525         --only if the parent periodicity is a part of the kpi calendar
526         l_flag:=false;
527         for j in 1..p_source_calendar.periodicity.count loop
528           if p_source_calendar.periodicity(j).aw_dim=p_source_calendar.parent_child(i).parent_dim_name then
529             l_flag:=true;
530             exit;
531           end if;
532         end loop;
533         if l_flag then
534           fill_in_target_periodicity(p_target_calendar,p_source_calendar,p_source_calendar.parent_child(i).parent_dim_name);
535         end if;
536       end if;
537     end loop;
538   end if;
539 Exception when others then
540   log_n('Exception in fill_in_target_periodicity '||sqlerrm);
541   raise;
542 End;
543 
544 /*
545 given a kpi and the dim set, find out the levels and their dim where there is zero code
546 */
547 procedure check_dim_zero_code(p_kpi varchar2,p_dim_set in out nocopy bsc_aw_adapter_kpi.dim_set_r) is
548 l_levels dbms_sql.varchar2_table;
549 Begin
550   bsc_metadata.get_zero_code_levels(p_kpi,p_dim_set.dim_set,l_levels);
551   for i in 1..p_dim_set.dim.count loop
552     for j in 1..p_dim_set.dim(i).levels.count loop
553       if bsc_aw_utility.in_array(l_levels,p_dim_set.dim(i).levels(j).level_name) then
554         --we can say there is zero code only if there is zero code level for this level
555         --we can do this since check_dim_zero_code comes after get_dim_properties in bsc_aw_adapter_kpi
556         if p_dim_set.dim(i).levels(j).zero_code_level is not null then
557           p_dim_set.dim(i).levels(j).zero_code:='Y';
558           p_dim_set.dim(i).zero_code:='Y';
559         end if;
560       end if;
561     end loop;
562   end loop;
563 Exception when others then
564   log_n('Exception in check_dim_zero_code '||sqlerrm);
565   raise;
566 End;
567 
568 /*
569 for each level get the pk,fk, datatype info
570 */
571 procedure get_dim_level_properties(p_kpi varchar2,p_dim in out nocopy bsc_aw_adapter_kpi.dim_r) is
572 Begin
573   for i in 1..p_dim.levels.count loop
574     p_dim.levels(i).level_type:=p_dim.property; --normal or time
575     bsc_metadata.get_dim_level_properties(p_dim.levels(i).level_name,
576     p_dim.levels(i).pk,p_dim.levels(i).fk,p_dim.levels(i).data_type,p_dim.levels(i).level_source);
577   end loop;
578   --get the filter for the lowest level in the kpi
579   get_dim_level_filter(p_kpi,p_dim.levels(1));
580 Exception when others then
581   log_n('Exception in get_dim_level_properties '||sqlerrm);
582   raise;
583 End;
584 
585 procedure get_dim_level_filter(p_kpi varchar2,p_level in out nocopy bsc_aw_adapter_kpi.level_r) is
586 Begin
587   bsc_metadata.get_dim_level_filter(p_kpi,p_level.level_name,p_level.filter);
588 Exception when others then
589   log_n('Exception in get_dim_level_filter '||sqlerrm);
590   raise;
591 End;
592 
593 /*
594 get base tables involved in the dim set
595 for each base table, get the level at which it is
596 get the measures the base table feeds
597 get the formula for each measure
598 --
599 each base table is a data source
600 get_base_table_levels : gets all the levels of the base table
601 we need all the levels because we need to know if the base table has more levels than the dim set
602 get_base_table_measures : gets the measures relevant to this dim set
603 --
604 consider this: dimset is at month,week...both lowest levels. 2 base tables. both at day level. due to this, datasource
605 periodicity was null.
606 (we were doing if p_dim_set.data_source(i).base_tables(1).periodicity.periodicity=p_dim_set.calendar.periodicity(j).periodicity then)
607 new logic: if the base table periodicity is not the same as any of the lowest periodicities, we create as many datasources for
608 each lowest level periodicity
609 more correction. in bsc, B table to S table mapping is stored. this means a day level B table may feed only week and another
610 day level B table feeds month.
611 if the B table is at a lower periodicity, we need to check which periodicity it feeds
612 */
613 procedure get_dim_set_data_source(p_kpi varchar2,p_dim_set in out nocopy bsc_aw_adapter_kpi.dim_set_r) is
614 l_base_tables dbms_sql.varchar2_table;
615 l_data_source bsc_aw_adapter_kpi.data_source_r;
616 l_ds_periodicity bsc_aw_adapter_kpi.periodicity_tb;
617 l_ds_copy bsc_aw_adapter_kpi.data_source_r;
618 l_feed_periodicity dbms_sql.number_table;
619 Begin
620   if p_dim_set.dim_set_type='actual' then
621     bsc_metadata.get_dim_set_base_tables(p_kpi,p_dim_set.dim_set,l_base_tables);
622   else
623     bsc_metadata.get_dim_set_target_base_tables(p_kpi,p_dim_set.dim_set,l_base_tables);
624   end if;
625   --every base table is a data source
626   for i in 1..l_base_tables.count loop
627     l_data_source:=null;
628     get_base_table_data_source(p_kpi,p_dim_set.dim_set,l_base_tables(i),l_data_source);
629     set_measure_properties(p_dim_set,l_data_source);
630     l_ds_periodicity.delete;
631     for j in 1..p_dim_set.calendar.periodicity.count loop
632       if p_dim_set.calendar.periodicity(j).lowest_level='Y'
633       and p_dim_set.calendar.periodicity(j).periodicity=l_data_source.base_tables(1).periodicity.periodicity then
634         l_ds_periodicity(l_ds_periodicity.count+1):=p_dim_set.calendar.periodicity(j);
635         exit;
636       end if;
637     end loop;
638     if l_ds_periodicity.count=0 then --B table lower periodicity
639       l_feed_periodicity.delete;
640       get_B_table_feed_periodicity(p_kpi,p_dim_set.dim_set,l_base_tables(i),l_feed_periodicity);
641       for j in 1..p_dim_set.calendar.periodicity.count loop
642         if p_dim_set.calendar.periodicity(j).lowest_level='Y'
643         and bsc_aw_utility.in_array(l_feed_periodicity,p_dim_set.calendar.periodicity(j).periodicity) then
644           l_ds_periodicity(l_ds_periodicity.count+1):=p_dim_set.calendar.periodicity(j);
645         end if;
646       end loop;
647     end if;
648     if l_ds_periodicity.count=0 then --B table at higher periodicity
649       for j in 1..l_feed_periodicity.count loop
650         for k in 1..p_dim_set.calendar.periodicity.count loop
651           if p_dim_set.calendar.periodicity(k).periodicity=l_feed_periodicity(j) then
652             l_ds_periodicity(l_ds_periodicity.count+1):=p_dim_set.calendar.periodicity(k);
653             exit;
654           end if;
655         end loop;
656       end loop;
657     end if;
658     if l_ds_periodicity.count=0 then --problem...
659       log('No target periodicity for B table '||l_base_tables(i)||' could be determined. Fatal...');
660       raise bsc_aw_utility.g_exception;
661     end if;
662     for j in 1..l_ds_periodicity.count loop
663       if g_debug then
664         log('Create datasource for B table '||l_base_tables(i)||' and periodicity '||l_ds_periodicity(j).periodicity);
665       end if;
666       p_dim_set.data_source(p_dim_set.data_source.count+1):=l_data_source; --copy B table info
667       p_dim_set.data_source(p_dim_set.data_source.count).ds_type:='initial';
668       p_dim_set.data_source(p_dim_set.data_source.count).std_dim:=p_dim_set.std_dim;
669       p_dim_set.data_source(p_dim_set.data_source.count).dim:=p_dim_set.dim;
670       p_dim_set.data_source(p_dim_set.data_source.count).calendar:=p_dim_set.calendar;
671       p_dim_set.data_source(p_dim_set.data_source.count).calendar.periodicity.delete;
672       p_dim_set.data_source(p_dim_set.data_source.count).calendar.periodicity(1):=l_ds_periodicity(j);
673       /*starting from the periodicity of the ds as the lowest level, get the upper part of cal hier*/
674       get_ds_relevant_cal_hier(p_dim_set.data_source(p_dim_set.data_source.count).calendar);
675       --copy this info into the inc data source
676       --later the data_source_stmt is populated differently for data source and inc data source
677       l_ds_copy:=p_dim_set.data_source(p_dim_set.data_source.count);
678       p_dim_set.inc_data_source(p_dim_set.data_source.count):=l_ds_copy;
679       p_dim_set.inc_data_source(p_dim_set.data_source.count).ds_type:='inc';
680     end loop;
681   end loop;
682 Exception when others then
683   log_n('Exception in get_dim_set_data_source '||sqlerrm);
684   raise;
685 End;
686 
687 /*set the measure properties from dimset into datasource (In get_base_table_data_source only the measure name is set)*/
688 procedure set_measure_properties(p_dim_set bsc_aw_adapter_kpi.dim_set_r,p_data_source in out nocopy bsc_aw_adapter_kpi.data_source_r) is
689 Begin
690   for i in 1..p_data_source.measure.count loop
691     for j in 1..p_dim_set.measure.count loop
692       if lower(p_dim_set.measure(j).measure)=lower(p_data_source.measure(i).measure) then
693         p_data_source.measure(i).measure_type:=p_dim_set.measure(j).measure_type;
694         p_data_source.measure(i).data_type:=p_dim_set.measure(j).data_type;
695         /*we do not set the formulas. formula is a DS property, not a dimset property*/
696         p_data_source.measure(i).forecast:=p_dim_set.measure(j).forecast;
697         p_data_source.measure(i).forecast_method:=p_dim_set.measure(j).forecast_method;
698         p_data_source.measure(i).cube:=p_dim_set.measure(j).cube;--null at this point
699         p_data_source.measure(i).countvar_cube:=p_dim_set.measure(j).countvar_cube;--null at this point
700         p_data_source.measure(i).fcst_cube:=p_dim_set.measure(j).fcst_cube;--null at this point
701         p_data_source.measure(i).property:=p_dim_set.measure(j).property;
702         exit;
703       end if;
704     end loop;
705   end loop;
706 Exception when others then
707   log_n('Exception in set_measure_properties '||sqlerrm);
708   raise;
709 End;
710 
711 /*the DS is at some higher level. get just the upper part of the cal hier */
712 procedure get_ds_relevant_cal_hier(p_calendar in out nocopy bsc_aw_adapter_kpi.calendar_r) is
713 l_upper_hier bsc_aw_adapter_kpi.cal_parent_child_tb;
714 Begin
715   bsc_aw_adapter_kpi.get_upper_cal_hier(p_calendar.parent_child,p_calendar.periodicity(1).aw_dim,l_upper_hier);
716   p_calendar.parent_child.delete;
717   for i in 1..l_upper_hier.count loop
718     p_calendar.parent_child(p_calendar.parent_child.count+1):=l_upper_hier(i);
719   end loop;
720 Exception when others then
721   log_n('Exception in get_ds_relevant_cal_hier '||sqlerrm);
722   raise;
723 End;
724 
725 --given a B table, what are the target periodicities it feeds
726 procedure get_B_table_feed_periodicity(p_kpi varchar2,p_dim_set varchar2,p_base_table varchar2,p_feed_periodicity out nocopy dbms_sql.number_table) is
727 Begin
728   bsc_metadata.get_B_table_feed_periodicity(p_kpi,p_dim_set,p_base_table,p_feed_periodicity);
729 Exception when others then
730   log_n('Exception in get_B_table_feed_periodicity '||sqlerrm);
731   raise;
732 End;
733 
734 /*
735 for a base table, finds the levels and measures and formula involved
736 for now, we are saying a data source has 1 base table
737 also find the periodicity of the base table
738 */
739 procedure get_base_table_data_source(
740 p_kpi varchar2,
741 p_dim_set varchar2,
742 p_base_table varchar2,
743 p_data_source in out nocopy bsc_aw_adapter_kpi.data_source_r) is
744 --
745 l_bt_levels dbms_sql.varchar2_table;
746 l_bt_feed_levels dbms_sql.varchar2_table;
747 l_bt_level_fks dbms_sql.varchar2_table; --contains the fk like city_code etc from the base table
748 l_bt_level_pks dbms_sql.varchar2_table;
749 l_ds_measures dbms_sql.varchar2_table;--data source measures , same as dim set measures
750 l_formula dbms_sql.varchar2_table;
751 l_level bsc_aw_adapter_kpi.level_r;
752 l_prj_table varchar2(100);
753 l_partition bsc_aw_utility.object_partition_r;
754 l_bt_copy bsc_aw_adapter_kpi.base_table_r;
755 Begin
756   bsc_metadata.get_base_table_levels(p_kpi,p_dim_set,p_base_table,l_bt_levels,l_bt_level_fks,l_bt_level_pks,l_bt_feed_levels);
757   bsc_metadata.get_base_table_measures(p_kpi,p_dim_set,p_base_table,l_ds_measures,l_formula);
758   bsc_metadata.get_base_table_periodicity(p_base_table,p_data_source.base_tables(1).periodicity.periodicity);
759   bsc_metadata.get_base_table_properties(p_base_table,l_prj_table,l_partition);
760   --
761   p_data_source.base_tables(1).base_table_name:=p_base_table;
762   p_data_source.base_tables(1).projection_table:=l_prj_table;
763   p_data_source.base_tables(1).table_partition:=l_partition;
764   for i in 1..l_bt_levels.count loop
765     p_data_source.base_tables(1).levels(i).level_name:=l_bt_levels(i);
766     p_data_source.base_tables(1).levels(i).fk:=l_bt_level_fks(i);
767     p_data_source.base_tables(1).levels(i).pk:=l_bt_level_pks(i);
768     p_data_source.base_tables(1).feed_levels(i):=l_bt_feed_levels(i); --Y or N
769   end loop;
770   for i in 1..l_ds_measures.count loop
771     p_data_source.measure(i).measure:=l_ds_measures(i);
772     p_data_source.measure(i).formula:=l_formula(i);
773   end loop;
774   /*if there is prj table, we add the prj table as another B table for the DS
775   */
776   if l_prj_table is not null then
777     l_bt_copy:=p_data_source.base_tables(1);
778     l_bt_copy.base_table_name:=l_prj_table;
779     l_bt_copy.projection_table:=null;
780     p_data_source.base_tables(p_data_source.base_tables.count+1):=l_bt_copy;
781   end if;
782 Exception when others then
783   log_n('Exception in get_base_table_data_source '||sqlerrm);
784   raise;
785 End;
786 
787 procedure get_dim_set_calendar(p_kpi varchar2,p_dim_set in out nocopy bsc_aw_adapter_kpi.dim_set_r) is
788 l_periodicity dbms_sql.number_table;
789 Begin
790   bsc_metadata.get_kpi_periodicities(p_kpi,p_dim_set.dim_set,l_periodicity);
791   for i in 1..l_periodicity.count loop
792     p_dim_set.calendar.periodicity(p_dim_set.calendar.periodicity.count+1).periodicity:=l_periodicity(i);
793   end loop;
794 Exception when others then
795   log_n('Exception in get_dim_set_calendar '||sqlerrm);
796   raise;
797 End;
798 
799 /*
800 given a calendar and periodicity, get the column name from bsc_db_calendar
801 */
802 function get_db_calendar_column(p_calendar number,p_periodicity number) return varchar2 is
803 Begin
804   return bsc_metadata.get_db_calendar_column(p_calendar,p_periodicity);
805 Exception when others then
806   log_n('Exception in get_db_calendar_column '||sqlerrm);
807   raise;
808 End;
809 
810 /*
811 this procedure gives the period in which there is a mix of forecast and real data
812 we need the following
813 kpi and periodicity : we use this to hit bsc_db_tables that will indicate the current period
814 calendar : with this, we will get the current year.
815 then we can say make the period
816 
817 called from bsc_aw_load_kpi
818 */
819 procedure get_forecast_current_period(
820 p_kpi varchar2,
821 p_calendar number,
822 p_periodicity number,
823 p_period out nocopy varchar2
824 ) is
825 --
826 l_year number;
827 l_period number;
828 Begin
829   --bsc_aw_calendar.get_calendar_current_year(p_calendar,l_year);
830   --we do not want to call bsc_aw_calendar.get_calendar_current_year. what if in the future, each kpi has its own
831   --current year?
832   bsc_metadata.get_kpi_current_period(p_kpi,p_periodicity,l_period,l_year);
833   p_period:=l_period||'.'||l_year;
834 Exception when others then
835   log_n('Exception in get_forecast_current_period '||sqlerrm);
836   raise;
837 End;
838 
839 /* period is in period.year format. periodicity is not specified or returned in this api.
840 we can later have caching
841 we may pass PRJ table which can have null current period*/
842 procedure get_table_current_period(p_table varchar2,p_period out nocopy varchar2) is
843 l_year number;
844 l_period number;
845 Begin
846   bsc_metadata.get_table_current_period(p_table,l_period,l_year);
847   if l_period is not null and l_year is not null then
848     p_period:=l_period||'.'||l_year;
849   end if;
850 Exception when others then
851   log_n('Exception in get_table_current_period '||sqlerrm);
852   raise;
853 End;
854 
855 procedure get_all_kpi_in_aw(
856 p_kpi out nocopy dbms_sql.varchar2_table,
857 p_kpi_dimset out nocopy dbms_sql.varchar2_table
858 ) is
859 --
860 l_kpi dbms_sql.varchar2_table;
861 l_dimset dbms_sql.varchar2_table;
862 Begin
863   bsc_metadata.get_all_kpi_in_aw(l_kpi);
864   for i in 1..l_kpi.count loop
865     l_dimset.delete;
866     bsc_metadata.get_kpi_dim_sets(l_kpi(i),l_dimset);
867     for j in 1..l_dimset.count loop
868       p_kpi(p_kpi.count+1):=l_kpi(i);
869       p_kpi_dimset(p_kpi_dimset.count+1):=l_dimset(j);
870     end loop;
871   end loop;
872 Exception when others then
873   log_n('Exception in get_all_kpi_in_aw '||sqlerrm);
874   raise;
875 End;
876 
877 /*
878 4486476
879 Issue is that PMV uses the short names for dimensions and measures. we use the dim table name and measure name from bsc
880 so we decided to do the lookup for them.
881 get_measures_for_short_names and get_dim_levels_for_short_names
882 */
883 procedure get_measures_for_short_names(
884 p_short_name dbms_sql.varchar2_table,
885 p_measure_name out nocopy dbms_sql.varchar2_table
886 ) is
887 Begin
888   bsc_metadata.get_measures_for_short_names(p_short_name,p_measure_name);
889 Exception when others then
890   log_n('Exception in get_measures_for_short_names '||sqlerrm);
891   raise;
892 End;
893 
894 procedure get_dim_levels_for_short_names(
895 p_short_name dbms_sql.varchar2_table,
896 p_dim_level_name out nocopy dbms_sql.varchar2_table
897 ) is
898 Begin
899   bsc_metadata.get_dim_levels_for_short_names(p_short_name,p_dim_level_name);
900 Exception when others then
901   log_n('Exception in get_dim_levels_for_short_names '||sqlerrm);
902   raise;
903 End;
904 
905 function is_level_used_by_aw_kpi(p_level varchar2) return boolean is
906 Begin
907   return bsc_metadata.is_level_used_by_aw_kpi(p_level);
908 Exception when others then
909   log_n('Exception in is_level_used_by_aw_kpi '||sqlerrm);
910   raise;
911 End;
912 
913 --------------------------
914 procedure init_all is
915 Begin
916   g_debug:=bsc_aw_utility.g_debug;
917   g_count:=0;
918 Exception when others then
919   null;
920 End;
921 
922 procedure log(p_message varchar2) is
923 Begin
924   bsc_aw_utility.log(p_message);
925 Exception when others then
926   null;
927 End;
928 
929 procedure log_n(p_message varchar2) is
930 Begin
931   log('  ');
932   log(p_message);
933 Exception when others then
934   null;
935 End;
936 
937 END BSC_AW_BSC_METADATA;