共计 8324 个字符,预计需要花费 21 分钟才能阅读完成。
My original tool introduced in blog Repository Information System for WebClient UI Component does not satisfy my colleagues, they have more requirement, as always
Some key requirements:
(1) I would like to know how many UI Component has used component set for example PROD_ALL defined in runtime repository.
(2) I have a data element for example COMT_PRODUCT_ID, I know it is used as context node attribute PRODUCT_ID in context node PRODUCT.
Now I would like to have a list of all WebClient UI component where the given data element is used as a certain context node attribute.
Here below is how I fulfill this requirement via some development.
Step 1
Create a database table CRMD_WEBUI_COM_H to store the relationship between a WebClient UI component and its assigned Genil component set
The technical definition of this table:
With this table, now it is easy for me to figure out how many UI component are using for example Genil component set PROD_ALL, that is 85:
Execute the following report to fill the content into this table:
REPORT crm_webui_tool_fill_bolset.
DATA: lt_ui TYPE TABLE OF o2appl-applname,
lt_dir TYPE TABLE OF o2pagdir-applname,
lv_loader TYPE REF TO cl_bsp_wd_stream_loader,
lv_bol_component_set TYPE string,
lv_xml TYPE string,
lt_result TYPE TABLE OF crmd_webui_com_h.
SELECT applname INTO TABLE lt_ui FROM o2appl WHERE
applname NOT LIKE 'Z%'.
SELECT DISTINCT applname INTO TABLE lt_dir FROM o2pagdir
FOR ALL ENTRIES IN lt_ui WHERE o2pagdir~applname = lt_ui-table_line
AND o2pagdir~pagekey = 'BSPWDCOMPONENT.DO'.
CREATE OBJECT lv_loader.
LOOP AT lt_dir ASSIGNING FIELD-SYMBOL(<page>).
CLEAR: lv_xml.
lv_xml = lv_loader->load_from_bsp_page( iv_bsp_appl = <page>
iv_bsp_page = 'Repository.xml' ).
CHECK lv_xml IS NOT INITIAL.
TRY.
CALL TRANSFORMATION bsp_wd_rt_rep_runtime
SOURCE XML lv_xml
RESULT model = lv_bol_component_set.
CATCH cx_root INTO DATA(cx_root).
WRITE:/ |xml parse error for component: {<page>}| COLOR COL_NEGATIVE.
CONTINUE.
ENDTRY.
APPEND INITIAL LINE TO lt_result ASSIGNING FIELD-SYMBOL(<result>).
<result> = VALUE #(appl = <page> bol_set = lv_bol_component_set).
ENDLOOP.
DELETE FROM crmd_webui_com_h.
INSERT crmd_webui_com_h FROM TABLE lt_result.
WRITE:/ |BOL index table inserted: {lines( lt_result) }| COLOR COL_NEGATIVE.
Step 2
Create a table CRMD_WUI_PROPERT to store the metadata of all Genil Component set.
The table contains Genil component model name, model node name and the DDIC structure used by the model node.
Use this report to fill content into it:
REPORT crm_webui_tool_fill_node_struc.
DATA:
lt_bol_set TYPE TABLE OF crmd_webui_com_h-bol_set,
lt_result TYPE TABLE OF crmd_wui_propert,
lt_obj_list TYPE crmt_ext_obj_name_tab.
SELECT DISTINCT bol_set INTO TABLE lt_bol_set FROM crmd_webui_com_h
WHERE bol_set <> space.
DATA(lo_core) = cl_crm_bol_core=>get_instance( ).
LOOP AT lt_bol_set ASSIGNING FIELD-SYMBOL(<bol>).
TRY.
lo_core->load_component_set(<bol>).
CATCH cx_root.
CONTINUE.
ENDTRY.
DATA(object_model) = CAST if_genil_obj_model(cl_crm_genil_model_service=>get_runtime_model() ).
object_model->get_object_list(IMPORTING et_object_list = lt_obj_list).
LOOP AT lt_obj_list ASSIGNING FIELD-SYMBOL(<object>).
TRY.
DATA(result) = object_model->get_object_properties(iv_object_name = <object>).
CATCH cx_root.
CONTINUE.
ENDTRY.
APPEND INITIAL LINE TO lt_result ASSIGNING FIELD-SYMBOL(<result>).
<result> = VALUE #( component_set = <bol> node_name = <object>
attr_struct_name = result-attr_struct ).
ENDLOOP.
ENDLOOP.
DELETE FROM crmd_wui_propert.
INSERT crmd_wui_propert FROM TABLE lt_result.
Step 3
Now it is time to extract needed information from each WebClient UI component. The information I need is:
- Context node class name
- the name of view where the context node is defined
- the name of WebClient UI component where the context node is defined
- the name of context node itself
- the name of Genil Model node which is bound to the current context node
- the DDIC structure used by the bound Genil Model node
Create a table CRMD_WUI_CONTX_H to store those information:
Execute this report to fill content into it:
REPORT crm_webui_tool_fill_context_h.
DATA: lt_pagdir TYPE TABLE OF o2pagdir,
lt_result TYPE TABLE OF crmd_wui_contx_h,
lt_struct TYPE TABLE OF crmd_wui_propert,
lt_set TYPE TABLE OF crmd_webui_com_h,
ls_flag TYPE crmd_wui_index_f,
lv_index TYPE int4 value 1,
lt_all_context_node TYPE TABLE OF vseoextend-clsname,
lt_context_node_name TYPE TABLE OF vseoattrib,
lo_cls TYPE REF TO cl_bsp_wd_context_node.
SELECT applname pagekey implclass INTO CORRESPONDING FIELDS OF TABLE lt_pagdir
FROM o2pagdir AS a INNER JOIN crmd_webui_com_h AS b ON a~applname = b~appl
WHERE pagekey LIKE '%.DO'.
SORT lt_pagdir BY applname.
SELECT * INTO TABLE lt_struct FROM crmd_wui_propert.
SELECT * INTO TABLE lt_set FROM crmd_webui_com_h.
SELECT clsname INTO TABLE lt_all_context_node FROM vseoextend WHERE refclsname =
'CL_BSP_WD_CONTEXT_NODE'.
SELECT clsname attvalue INTO CORRESPONDING FIELDS OF TABLE lt_context_node_name
FROM vseoattrib FOR ALL ENTRIES IN lt_all_context_node WHERE clsname =
lt_all_context_node-table_line AND cmpname = 'BASE_ENTITY_NAME'.
DATA(lv_line) = lines(lt_pagdir).
LOOP AT lt_pagdir ASSIGNING FIELD-SYMBOL(<page>).
CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
EXPORTING
percentage = (lv_index * 100) / lv_line
text = | UI Component being scanned: {<page>-applname} |.
AT NEW applname.
DATA(lo_model) = cl_bsp_wd_appl_model=>get_appl_model( EXPORTING iv_bsp_appl = <page>-applname
iv_model_type = 'CL_BSP_WD_APPL_MODEL_DDIC' ).
ENDAT.
DATA(lv_name) = lo_model->get_runtime_context(<page>-implclass).
DATA(lt_context) = lo_model->get_runtime_context_nodes(lv_name).
LOOP AT lt_context ASSIGNING FIELD-SYMBOL(<context>).
TRANSLATE <context>-implclass TO UPPER CASE.
READ TABLE lt_context_node_name ASSIGNING FIELD-SYMBOL(<node_name>)
WITH KEY clsname = <context>-implclass.
CHECK sy-subrc = 0.
REPLACE ALL OCCURRENCES OF '''' IN <node_name>-attvalue WITH space.
READ TABLE lt_set ASSIGNING FIELD-SYMBOL(<set>) WITH KEY appl = <page>-applname.
CHECK sy-subrc = 0.
READ TABLE lt_struct ASSIGNING FIELD-SYMBOL(<struct>) WITH KEY component_set = <set>-bol_set
node_name = <node_name>-attvalue.
CHECK sy-subrc = 0.
APPEND INITIAL LINE TO lt_result ASSIGNING FIELD-SYMBOL(<result>).
<result> = VALUE #( context_node_cls = <context>-implclass
component = <page>-applname
view_name = <page>-pagekey
context_node_name = <context>-name
genil_node_name = <node_name>-attvalue
attr_struct_name = <struct>-attr_struct_name
).
ENDLOOP.
lv_index = lv_index + 1.
ENDLOOP.
DELETE FROM crmd_wui_contx_h.
INSERT crmd_wui_contx_h FROM TABLE lt_result.
WRITE:/ |Entries inserted: {lines( lt_result) }| COLOR COL_GROUP.
Step 4
As the last step, now we need to provide the data type for each context node attribute. As a result I create this table CRMD_WUI_CN_ATTR to store the context node name, the component where it is defined, and each attribute name and data element name used by this context node attribute.
The table content is filled by this report:
REPORT crm_webui_tool_fill_cont_attr.
TYPES: BEGIN OF ty_field_type,
fieldname TYPE dfies-fieldname,
rollname TYPE dfies-rollname,
END OF ty_field_type.
TYPES: tt_field_type TYPE STANDARD TABLE OF ty_field_type WITH KEY fieldname.
TYPES: BEGIN OF ty_struct_types,
struct_name TYPE seocpdname,
field_detail TYPE tt_field_type,
END OF ty_struct_types.
TYPES: tt_struct_types TYPE STANDARD TABLE OF ty_struct_types WITH KEY struct_name.
DATA: lt_context_h TYPE TABLE OF crmd_wui_contx_h,
lt_result TYPE TABLE OF crmd_wui_cn_attr,
lt_dfies_tab TYPE comt_dfies_tab,
lt_struc_types TYPE tt_struct_types.
FIELD-SYMBOLS: <type> TYPE ty_struct_types.
SELECT * INTO TABLE lt_context_h FROM crmd_wui_contx_h.
LOOP AT lt_context_h ASSIGNING FIELD-SYMBOL(<context_node>).
DATA(lo_model) = cl_bsp_wd_appl_model=>get_appl_model(
EXPORTING iv_bsp_appl = <context_node>-component
iv_model_type = 'CL_BSP_WD_APPL_MODEL_DDIC' ).
DATA(lt_attr) = lo_model->get_context_node_attr( iv_context_node_class = <context_node>-context_node_cls
iv_mark_ext_attributes = abap_true ).
READ TABLE lt_struc_types ASSIGNING <type> WITH KEY struct_name = <context_node>-attr_struct_name.
IF sy-subrc <> 0.
CALL FUNCTION 'DDIF_FIELDINFO_GET'
EXPORTING
tabname = <context_node>-attr_struct_name
TABLES
dfies_tab = lt_dfies_tab.
DATA(lt_field_type) = CORRESPONDING tt_field_type(lt_dfies_tab).
APPEND INITIAL LINE TO lt_struc_types ASSIGNING <type>.
<type> = VALUE #(struct_name = <context_node>-attr_struct_name field_detail = lt_field_type).
CLEAR: lt_dfies_tab.
ENDIF.
LOOP AT lt_attr ASSIGNING FIELD-SYMBOL(<attr>).
FIND '.' IN <attr>.
CHECK sy-subrc = 0.
SPLIT <attr> AT '.' INTO TABLE DATA(lt_field_name).
READ TABLE <type>-field_detail ASSIGNING FIELD-SYMBOL(<field_type>) WITH KEY
fieldname = lt_field_name[2].
CHECK sy-subrc = 0.
APPEND INITIAL LINE TO lt_result ASSIGNING FIELD-SYMBOL(<result>).
<result> = CORRESPONDING #(<context_node>).
<result>-attr_name = lt_field_name[2].
<result>-attr_type = <field_type>-rollname.
ENDLOOP.
ENDLOOP.
DELETE FROM crmd_wui_cn_attr.
INSERT crmd_wui_cn_attr FROM TABLE lt_result.
WRITE:/ |Lines inserted: {lines( lt_result) }| COLOR COL_NEGATIVE.
Once done, now it is very easy to answer the second question raised in the beginning of this blog:
How many UI Component have context node which uses data element COMT_PRODUCT_ID as context node attribute type?
Just query field ATTR_TYPE with value COMT_PRODUCT_ID:
And you get a list of all 993 usages:
要获取更多 Jerry 的原创文章,请关注公众号 ” 汪子熙 ”: