开发者们可以在编程中使用各种动态技术,比如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)前提

要读懂本节,需要两方面的知识,

  1. 基本的ABAP面向对象知识。
  2. 基本的BRF+知识。

2)需求

通过一个简单的report程序来创建决策表和它的条目。

3)使用的接口

  1. IF_FDT_FACTORY
  2. IF_FDT_DECISION_TABLE
  3. 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(IMPORTINGet_message           = lt_messageev_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(IMPORTINGet_message           = lt_messageev_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(IMPORTINGet_message           = lt_messageev_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.

执行后可以看到结果,如下图,

前往BRF+工作台,按ID搜索对象

可以查询到结果,

已经成功创建了决策表,也可以在上文创建的应用下找到这个决策表,

3,动态获取函数参数

函数的参数是在创建BRF+函数时定义的,在某些场景下,我们需要动态地获取这些参数,以供程序使用。

比如,用户创建了若干公式,公式中存在常量,也存在不同的需要用户输入的运算数,这些运算数即函数的参数。程序需要获取到用户所选择的公式中需要输入的运算数,这样才能告诉用户,需要在界面输入哪些变量的值。

对于这个功能的实现方式,我曾经在SCN上提问,最后自己找到了答案。现把答案转贴在这里。

在调用BRG+函数时,需要获取上下文对象,而函数的参数的名字和ID,就位于上下文对象中的属性MT_NAME_VALUE中,如下图

可以为类CL_FDT_CONTEXT创建增强,新增方法GET_MT_NAME_VALUES,以读取私有属性MT_NAME_VALUE,

  methods GET_MT_NAME_VALUESexportingvalue(ET_NAME_VALUE) type HASHED TABLE .

方法的实现如下,

METHOD get_mt_name_values .et_name_value = me->mt_name_value.ENDMETHOD.

接下来在自己的程序中调用该方法,

TYPES:BEGIN OF s_name_id_value,id               TYPE if_fdt_types=>id,name             TYPE abap_parmname,data_object_type TYPE if_fdt_types=>data_object_type,value            TYPE REF TO data,value_set        TYPE abap_bool,END OF s_name_id_value .
TYPES:t_name_id_value TYPE HASHED TABLE OF s_name_id_valueWITH UNIQUE KEY name .DATA: t_name TYPE t_name_id_value.DATA(lo_fuction) = cl_fdt_factory=>if_fdt_factory~get_instance()->get_function( '005056A4CCA61ED8A8924F0F3F4F1D98' ).
*

DATA(lo_context) = CAST cl_fdt_context( lo_fuction->get_process_context( ) ).lo_context->get_mt_name_values( IMPORTING et_name_value = t_name ).

就可以得到相关信息。

转载于:https://www.cnblogs.com/hhelibeb/p/9571707.html

我的BRF+自学教程(三):动态技术相关推荐

  1. 我的BRF+自学教程(二):跟踪模式(tracing)

    使用自开发程序来处理业务逻辑时,处理过程通常是个黑箱,业务顾问和业务用户不知道程序的具体运行方式,要依赖文档和频繁的沟通来确认实际情况. BRFplus可以通过配置的方式实现业务逻辑,使得业务人员把业 ...

  2. 计算机接口与通信技术考试题,全国2010年10月自学考试计算机通信接口技术试题...

    全国2010年10月高等教育自学考试 计算机通信接口技术试题 课程代码:02369 注:接口芯片的控制字请参阅附录. 一.单项选择题(本大题共20小题,每小题1分,共20分) 在每小题列出的四个备选项 ...

  3. python商城源码_自学Python才几天,就成功编写出俄罗斯方块游戏,附自学教程

    人们常说,python不适合做游戏,但我偏爱玩游戏,做不了大的,做个小的也行啊. 于是,我在自己毫无基础的条件下,用两天时间学python基础理论,再用已有的俄罗斯方块游戏源码和源文件,在我的不懈努力 ...

  4. 区块链教程(三):Solidity编程基础

    注:本教程为技术教程,不谈论且不涉及炒作任何数字货币 区块连教程(一):前置知识-linux补充 区块链教程(二):基础概念介绍 区块链教程(三):Solidity编程基础 区块链教程(四):搭建私链 ...

  5. MVC 5 + EF6 入门完整教程14 -- 动态生成面包屑导航

    MVC 5 + EF6 入门完整教程14 -- 动态生成面包屑导航 原文:MVC 5 + EF6 入门完整教程14 -- 动态生成面包屑导航 上篇文章我们完成了 动态生成多级菜单 这个实用组件. 本篇 ...

  6. python爬虫入门教程(三):淘女郎爬虫 ( 接口解析 | 图片下载 )

    2019/10/28更新 网站已改版,代码已失效(其实早就失效了,但我懒得改...)此博文仅供做思路上的参考 代码使用python2编写,因已失效,就未改写成python3 爬虫入门系列教程: pyt ...

  7. 直播平台源码搭建教程盘点直播技术中的编解码、直播协议、网络传输与简单实现

    直播平台源码搭建教程盘点直播技术中的编解码.直播协议.网络传输与简单实现 Live CheatSheet | 直播技术理论基础与实践概论 音视频直播的基本流程都是采集 → 编码推流 → 网络分发 → ...

  8. 零基础Python完全自学教程15:Python中的列表

    欢迎你来到站长学堂,学习站长在线出品的在线课程<零基础 Python完全自学教程>今天给大家分享的是第14课< Python中的列表 >.本节课是一个大课,我分了这些知识点进行 ...

  9. 六个office免费学习的精品教程 office自学教程让你从小白到高手

    今天给大家分享六个免费学习的精品教程,包括了word,ppt,excel常用的办公三剑客,学会这三个让你办公无忧,也能让你靠这些技术找到一份好工作,这些office自学教程让你从小白到高手. 一.PP ...

最新文章

  1. flex与java实现增删改查
  2. cdoj841-休生伤杜景死惊开 (逆序数变形)【线段树 树状数组】
  3. 多线程:synchronize、volatile、Lock 的区别与用法
  4. bzoj3697 采药人的路径
  5. go post请求的响应数据渲染到html模板_干货你需要了解的六种渲染模式
  6. 有朋友问了数据库ID不连续,怎么获取上一篇和下一篇的文章?(不是所有情况都适用)...
  7. java、js的编码、解码
  8. 热敏打印机ESCPOS指令封装类,票据打印从此轻松,佳博系列实测通过
  9. windows2016服务器优化,Windows server 2016系统基本优化设置
  10. 如何提高人际交往的沟通技巧
  11. linux中文件夹删不掉,Linux无法删除文件夹 Device or resource busy
  12. 选修课程期末作业 : 大象基金交易信息系统分析与设计报告
  13. Airtest微信朋友圈自动点赞
  14. 暴力破解:利用正则功能自动提取爆破结果中的特征值
  15. 计算机程序判断素数(一)
  16. 从平民到帝皇——给企业主的启示
  17. 数据网站 免费数据网站
  18. 云闪付UA 通过user-agent判断用户是否使用云闪付
  19. 体验deepin作为办公系统
  20. Ocelot(二)- 请求聚合

热门文章

  1. GEF+EMF Step By Step
  2. 类的继承性 分别定义Teacher(教师)类和Cadre(干部)类,采用多重继承方式由这两个类派生出新类Teacher_Cadre(教师兼干部)。
  3. 网络连接错误代码大全及处理办法
  4. imx6ull交叉编译libmodbus
  5. Struts分页代码
  6. 货运APP开发面临市场的考验
  7. ChatGPT 将成“天选打工人”?OpenAI CEO:对发明“有点害怕”
  8. 服务容错保护Hystrix服务网关Zuul
  9. [TIST 2022] No Free Lunch Theorem for Security and Utility in Federated Learning
  10. Keepalived无法绑定VIP故障排查经历