我的BRF+自学教程(三):动态技术
开发者们可以在编程中使用各种动态技术,比如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 = . 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 = . 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 = . 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 = . 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 = .
ls_column-object_id = lv_element2_id.
ls_column-is_result = abap_false. INSERT ls_column INTO TABLE lts_column. * 填充结果列元素
ls_column-col_no = .
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 = .
ls_table_data-col_no = .
ls_range-position = .
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 = .
ls_table_data-col_no = .
ls_range-position = .
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 = . ls_table_data-col_no = . 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_VALUES
exporting
value(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_value
WITH 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 ).
就可以得到相关信息。
我的BRF+自学教程(三):动态技术的更多相关文章
- 我的BRF+自学教程(一):公式(formula)
Business Rule Framework Plus(业务规则框架,以下简称BRFplus或BRF+)是一个强大的工具, 它允许用户以直观的方式对规则建模,并在不同的应用程序中重用这些规则.通过它 ...
- 我的BRF+自学教程(二):跟踪模式(trace mode)
使用自开发程序来处理业务逻辑时,处理过程通常是个黑箱,业务顾问和业务用户不知道程序的具体运行方式,要依赖文档和频繁的沟通来确认实际情况. BRFplus可以通过配置的方式实现业务逻辑,使得业务人员把业 ...
- HMM 自学教程(三)隐藏模式
本系列文章摘自 52nlp(我爱自然语言处理: http://www.52nlp.cn/),原文链接在 HMM 学习最佳范例,这是针对 国外网站上一个 HMM 教程 的翻译,作者功底很深,翻译得很精彩 ...
- 六个office免费学习的精品教程 office自学教程让你从小白到高手
今天给大家分享六个免费学习的精品教程,包括了word,ppt,excel常用的办公三剑客,学会这三个让你办公无忧,也能让你靠这些技术找到一份好工作,这些office自学教程让你从小白到高手. 一.PP ...
- python怎么自学?今日头条技术大佬的真实经历分享
大家好,我是武州,27岁,目前在字节跳动担任Python后端工程师一职. (摆拍一下,假装是保安) 在开始今天的文章之前,不知道你们有没有遇到过这样的问题: 大学没学到什么实质技术,毕业后找不到高薪的 ...
- HMM 自学教程(八)总结
本系列文章摘自 52nlp(我爱自然语言处理: http://www.52nlp.cn/),原文链接在HMM 学习最佳范例,这是针对国外网站上一个 HMM 教程的翻译,作者功底很深,翻译得很精彩,且在 ...
- HMM 自学教程(七)前向后向算法
本系列文章摘自 52nlp(我爱自然语言处理: http://www.52nlp.cn/),原文链接在 HMM 学习最佳范例,这是针对 国外网站上一个 HMM 教程 的翻译,作者功底很深,翻译得很精彩 ...
- HMM 自学教程(六)维特比算法
本系列文章摘自 52nlp(我爱自然语言处理: http://www.52nlp.cn/),原文链接在 HMM 学习最佳范例,这是针对 国外网站上一个 HMM 教程 的翻译,作者功底很深,翻译得很精彩 ...
- HMM 自学教程(五)前向算法
本系列文章摘自 52nlp(我爱自然语言处理: http://www.52nlp.cn/),原文链接在 HMM 学习最佳范例,这是针对 国外网站上一个 HMM 教程 的翻译,作者功底很深,翻译得很精彩 ...
随机推荐
- 在SoapUI中模拟用户操作
SoapUI作为一款接口测试工具,具有极大的灵活性和拓展性.它可以通过安装插件,拓展其功能.Selenium作为一款Web自动化测试插件可以很好的与SoapUI进行集成.如果要在SoapUI中模拟用户 ...
- https创建请求UrL报错: 未能为 SSL/TLS 安全通道建立信任关系
1.项目中异常报错如下: 2.百度结果:原来是 网站没有使用SSL证书或者是SSl证书失效了的缘故. 3.具体解决方案如下: )导入命名空间 using System.Net.Security; us ...
- Mybatis foreach标签含义
背景 考虑以下场景: InfoTable(信息表): Name Gender Age Score 张三 男 21 90 李四 女 20 87 王五 男 22 92 赵六 女 19 94 孙七 女 23 ...
- Netty实战十之编解码器框架
编码和解码,或者数据从一种特定协议的格式到另一种格式的转换.这些任务将由通常称为编解码器的组件来处理.Netty提供了多种组件,简化了为了支持广泛的协议而创建自定义的编解码器的过程.例如,如果你正在构 ...
- Hibernate入门(四)---------一级缓存
Hibernate一级缓存 Hibernate的一级缓存就是指Session缓存,Session缓存是一块内存空间,用来存放相互管理的java对象,在使用Hibernate查询对象的时候,首先会使用对 ...
- react children
children react 中,属性名是一一对应的,除了children. 对于一个组件来说,其this.props.children拿到的是什么呢???举个
- VMWAR-workstatuon
https://blog.csdn.net/felix__h/article/details/82853501 链接中的秘钥可用~感谢原文作者 下载安装: 官网下载地址:https://www.vmw ...
- vue.js及项目实战[笔记]— 03 vue.js插件
一. vue补充 1. 获取DOM元素 救命稻草,document.querySelector 在template中标示元素`ref = "xxx" 在要获取的时候,this.$r ...
- AI在汽车中的应用:实用深度学习
https://mp.weixin.qq.com/s/NIza8E5clC18eMF_4GMwDw 深度学习的“深度”层面源于输入层和输出层之间实现的隐含层数目,隐含层利用数学方法处理(筛选/卷积)各 ...
- [性能调优]PeopleSoft Trace 分析工具 - TraceMagic
PeopleSoft Trace 文件包含大量的信息,在前面文章讲解过如何查看trace日志文件,这边文章介绍一个工具可以很好的分析trace日志文件. TraceMagic 是由oracle开发的一 ...