开发者们可以在编程中使用各种动态技术,比如RTTS,比如通过动态的类创建和多态来实现功能的平滑扩展。BRF+对象也有一定动态能力。本文将介绍3种不同场景下的动态实践方式。其中第一种是纯配置的,第二和第三种是编程相关的。
本文链接:https://www.cnblogs.com/hhelibeb/p/9571707.html
我的BRF+教程系列:https://www.cnblogs.com/hhelibeb/tag/BRFplus/
1,动态表达式(Dynamic Expression)
动态表达式是一种特殊类型的表达式,它可以用来实现对其它表达式的动态调用。动态表达式的应用场景之一是,有很多个表达式可以供用户选择,这些表达式使用基本一样的上下文对象,你不希望为每个表达式创建一个函数(因为创建它们的过程太繁琐),而是希望在一个统一的入口函数去调用。
1)选项被调用的表达式(Called Expression):选择一个表达式,将它分配给动态表达式。被分配的表达式会在运行期间被动态表达式调用。注意,虽然被称为被调用的表达式,但是它并不是被动态调用的表达式,它的返回结果才是被动态调用的表达式的ID。Called Expression可以处理动态表达式的上下文,结果中必须包含一个表达式的ID,该表达式的结果会被传回给动态表达式。
结果数据对象(Result Data Object:)结果数据对象可以使用任何种类的对象。然而,很重要的一点是确保第二个被调用的表达式的结果数据对象和动态表达式的结果数据对象是兼容的。
2)限制动态表达式可以提供灵活性,但它也有缺陷,因为动态表达式类型的特质,使得某些大部分可以应用在其它BRF+表达式上的检查无法应用在动态表达式上面。所以这可能导致一些设计缺陷无法被检查出来,只有在运行期间才会暴露。此外,动态表达式是不支持代码生成模式的,只能使用解释模式,这使得它的性能不太好,在对时间要求高或数据负载量大的时候不建议使用它。
3)例子实际操作部分比较简单,读完上面的文字之后应该可以很顺利地出来,这里就不再一图一图地贴了。可以参考官方文档。
2,动态创建决策表(Decision Table)通过使用ABAP代码,可以动态地创建BRFplus中的decisiong table和function等对象。
(本节的内容基本来自于Create decision table & it’s entries dynamically in BRF + Workbench through API)
1)前提要读懂本节,需要两方面的知识,
基本的ABAP面向对象知识。
基本的BRF+知识。
2)需求通过一个简单的report程序来创建决策表和它的条目。
3)使用的接口IF_FDT_FACTORY
IF_FDT_DECISION_TABLE
IF_FDT_FUNCTION
4)创建应用在工作台中创建一个应用,接下来将会在这个应用中动态地创建决策表。
5)复制代码把以下代码粘贴到自定义程序中,代码的具体意义写在注释中,注意ID要替换成你自己创建的BRF+应用的ID
DATA: lo_factory
TYPE REF TO if_fdt_factory,
lt_message
TYPE if_fdt_types=>t_message,
lv_message
TYPE string,
lv_boolean
TYPE abap_bool,
lo_element
TYPE REF TO if_fdt_element,
lo_table
TYPE REF TO if_fdt_table,
lo_structure
TYPE REF TO if_fdt_structure,
lv_element1_id TYPE if_fdt_types=>id,
lv_element2_id TYPE if_fdt_types=>id,
lv_element3_id TYPE if_fdt_types=>id,
lv_structure_id TYPE if_fdt_types=>id,
lo_constant
TYPE REF TO if_fdt_constant,
ls_element
TYPE if_fdt_structure=>s_element,
lts_element
TYPE if_fdt_structure=>ts_element,
lv_string
TYPE string,
ls_range
TYPE if_fdt_decision_table=>s_range,
ls_table_data
TYPE if_fdt_decision_table=>s_table_data,
lo_decision_table TYPE REF TO if_fdt_decision_table,
lo_function
TYPE REF TO if_fdt_function,
lo_context
TYPE REF TO if_fdt_context,
lts_context_id TYPE if_fdt_types=>ts_object_id,
lts_table_data TYPE if_fdt_decision_table=>ts_table_data,
lts_column
TYPE if_fdt_decision_table=>ts_column,
lv_actv_failed TYPE abap_bool,
lx_fdt
TYPE REF TO cx_fdt,
lv_dt_id
TYPE if_fdt_types=>id,
ls_column
LIKE LINE OF lts_column.
FIELD-SYMBOLS: <ls_message> TYPE if_fdt_types=>s_message,
<lv_value> TYPE any.
* 获取FDT工厂实例,使用上面创建的应用ID
lo_factory = cl_fdt_factory=>if_fdt_factory~get_instance(
'005056A4CCA61ED8AA9AAF84A7712616' ).
*创建数据对象
lo_element ?= lo_factory->get_data_object(
iv_data_object_type = if_fdt_constants=>gc_data_object_type_element ).
lo_element->if_fdt_transaction~enqueue( ).
lo_element->if_fdt_admin_data~set_name( 'IV_VAR1' ).
lo_element->set_element_type( if_fdt_constants=>gc_element_type_text ).
lo_element->if_fdt_transaction~activate(
IMPORTING
et_message
= lt_message
ev_activation_failed = lv_boolean ).
IF lv_boolean EQ abap_true.
*如果激活失败,需要处理
lo_element->if_fdt_transaction~dequeue( ).
ELSE.
lo_element->if_fdt_transaction~save( ).
lo_element->if_fdt_transaction~dequeue( ).
* 通常需要把ID单独存下来,以便后续操作
lv_element1_id = lo_element->mv_id.
ls_element-position = 1.
ls_element-element_id = lv_element1_id.
APPEND ls_element TO lts_element.
ENDIF.
INSERT lv_element1_id INTO TABLE lts_context_id.
*创建另一个元素
lo_element ?= lo_factory->get_data_object(
iv_data_object_type = if_fdt_constants=>gc_data_object_type_element ).
lo_element->if_fdt_transaction~enqueue( ).
lo_element->if_fdt_admin_data~set_name( 'IV_VAR2' ).
* 设置元素类型(可以搜索if_fdt_constants=>gc_element_type_* 得到可用元素类型列表
lo_element->set_element_type( if_fdt_constants=>gc_element_type_text ).
lo_element->if_fdt_transaction~activate(
IMPORTING
et_message
= lt_message
ev_activation_failed = lv_boolean ).
IF lv_boolean EQ abap_true.
lo_element->if_fdt_transaction~dequeue( ).
ELSE.
lo_element->if_fdt_transaction~save( ).
lo_element->if_fdt_transaction~dequeue( ).
lv_element2_id = lo_element->mv_id.
ls_element-position = 2.
ls_element-element_id = lv_element2_id.
APPEND ls_element TO lts_element.
ENDIF.
INSERT lv_element2_id INTO TABLE lts_context_id.
* 创建结果数据元素
lo_element ?= lo_factory->get_data_object(
iv_data_object_type = if_fdt_constants=>gc_data_object_type_element ).
lo_element->if_fdt_transaction~enqueue( ).
lo_element->if_fdt_admin_data~set_name( 'EV_RESULT' ).
lo_element->set_element_type( if_fdt_constants=>gc_element_type_text ).
lo_element->if_fdt_transaction~activate(
IMPORTING
et_message
= lt_message
ev_activation_failed = lv_boolean ).
IF lv_boolean EQ abap_true.
lo_element->if_fdt_transaction~dequeue( ).
ELSE.
lo_element->if_fdt_transaction~save( ).
lo_element->if_fdt_transaction~dequeue( ).
lv_element3_id = lo_element->mv_id.
ls_element-position = 3.
ls_element-element_id = lv_element3_id.
APPEND ls_element TO lts_element.
ENDIF.
INSERT lv_element3_id INTO TABLE lts_context_id.
* 填充第1列元素
ls_column-col_no
= 1.
ls_column-object_id = lv_element1_id.
ls_column-is_result = abap_false.
INSERT ls_column INTO TABLE lts_column.
* 填充第2列元素
ls_column-col_no = 2.
ls_column-object_id = lv_element2_id.
ls_column-is_result = abap_false.
INSERT ls_column INTO TABLE lts_column.
* 填充结果列元素
ls_column-col_no = 3.
ls_column-object_id = lv_element3_id.
ls_column-is_result = abap_true.
INSERT ls_column INTO TABLE lts_column.
* 创建并设置决策表表达式
lo_decision_table ?= lo_factory->get_expression( iv_expression_type_id = if_fdt_constants=>gc_exty_decision_table ).
* 对表达式加锁.
lo_decision_table->if_fdt_transaction~enqueue( abap_true ).
* 设置表列
lo_decision_table->set_columns( its_column = lts_column ).
lo_decision_table->if_fdt_admin_data~set_name( 'DT_TEST' ). "user defined name. DT_TEST is the decision table Name
* 使用工厂对象创建一个函数实例.
lo_function ?= lo_factory->get_function( ).
* 对函数加锁.
lo_function->if_fdt_transaction~enqueue( ).
* 设置函数上下文对象.
lo_function->set_context_data_objects( lts_context_id ).
lo_function->if_fdt_admin_data~set_name( 'FN_TEST' ). "自定义函数名
* 设置函数根表达式.
lo_function->set_expression( lo_decision_table->mv_id ).
* 设置单元格(1,1)的条件
ls_table_data-row_no = 1.
ls_table_data-col_no = 1.
ls_range-position = 1.
ls_range-sign = if_fdt_range=>gc_sign_include.
ls_range-option = if_fdt_range=>gc_option_equal.
CREATE DATA ls_range-r_low_value TYPE if_fdt_types=>element_text.
ASSIGN ls_range-r_low_value->* TO <lv_value>. <lv_value> = 'MOURI'.
INSERT ls_range INTO TABLE ls_table_data-ts_range.
INSERT ls_table_data INTO TABLE lts_table_data.
CLEAR ls_table_data. .
*设置单元格(1,2)的条件
ls_table_data-row_no = 1.
ls_table_data-col_no = 2.
ls_range-position = 1.
ls_range-sign = if_fdt_range=>gc_sign_include.
ls_range-option = if_fdt_range=>gc_option_equal.
CREATE DATA ls_range-r_low_value TYPE if_fdt_types=>element_text.
ASSIGN ls_range-r_low_value->* TO <lv_value>. <lv_value> = 'TECH'.
INSERT ls_range INTO TABLE ls_table_data-ts_range.
INSERT ls_table_data INTO TABLE lts_table_data.
CLEAR ls_table_data. **在单元格(1, 3)得到结果
ls_table_data-row_no = 1. ls_table_data-col_no = 3.
CREATE DATA ls_table_data-r_value TYPE if_fdt_types=>element_text.
ASSIGN ls_table_data-r_value->* TO <lv_value>. <lv_value> = 'MOURITECH'.
INSERT ls_table_data INTO TABLE lts_table_data.
CLEAR ls_table_data.
* 设置完全的表数据.
lo_decision_table->set_table_data( its_data = lts_table_data ).
* 保存并激活.
lo_function->if_fdt_transaction~activate(
EXPORTING iv_deep = abap_true
IMPORTING et_message = lt_message
ev_activation_failed = lv_actv_failed ).
* 如果成功,先保存对象。无论成功失败,释放全部锁
IF lv_actv_failed EQ abap_true.
lo_function->if_fdt_transaction~dequeue( iv_deep = abap_true ).
WRITE : / 'Deep activation failed'.
LOOP AT lt_message ASSIGNING <ls_message>.
MESSAGE ID <ls_message>-msgid TYPE <ls_message>-msgty NUMBER <ls_message>-msgno
WITH <ls_message>-msgv1 <ls_message>-msgv2 <ls_message>-msgv3 <ls_message>-msgv4 INTO lv_message.
WRITE: / 'Reason : -',lv_message.
ENDLOOP.
ELSE.
TRY.
lv_dt_id = lo_decision_table->mv_id.
lo_function->if_fdt_transaction~save( iv_deep = abap_true ).
WRITE : 'The ID of the decision table created is:' ,lv_dt_id. .
CATCH cx_fdt INTO lx_fdt.
WRITE : / 'Save failed with exception'.
LOOP AT lx_fdt->mt_message ASSIGNING <ls_message>.
WRITE :/ <ls_message>-text.
ENDLOOP.
ENDTRY.
lo_function->if_fdt_transaction~dequeue( iv_deep = abap_true ).
ENDIF.