在平常的开发过程当中,咱们经常要处理不一样来源的数据。数据可能来自不可靠的外部系统、不可靠的用户输入和甚至设计有误的数据库表,所以,对数据有效性进行验证是必要的工做。html
开源工具ABAP Data Validator是一个使用ABAP开发的数据验证工具,它能够简化开发者在这方面的工做。本文将介绍它的用法和一些设计思路。git
本文连接:http://www.javashuo.com/article/p-xyujegzf-ha.htmlgithub
原创内容,转载请注明web
具体而言,ABAP Data Validator将经过如下的思路简化数据有效性验证方面的工做:正则表达式
为了实现以上目的,该工具实现了一些功能:数据库
ABAP Data Validator目前支持如下类型的检查(持续更新中):编程
此外,它也支持对内表字段的必填检查、根据数据元素的类型进行检查等功能,下文会详细介绍。服务器
ABAP Data Validator支持多种检查方式,下面会由简单到复杂进行逐一介绍。函数
对于每种数据类型,ABAP Data Validator会有一个专门的检查类,能够用这些检查类的is_valid方法来检查变量的值是否有效,就像使用abap的内置函数那样。好比,要检查一个字符串是不是有效的邮箱地址,能够用以下代码实现,工具
IF zcl_adv_email_check=>is_valid( 'example@github.com' ). "do something ENDIF.
全部的检查类都实现了接口zif_adv_check,所以它们都拥有静态方法is_valid,以下图(为了方便阅读,图中没有包含所有的实现类),
对于类方法而言,is_valid是个别名,也能够不使用别名来调用接口方法:
IF zcl_adv_email_check=>zif_adv_check~is_valid( 'example@github.com' ). "do something ENDIF.
固然并不推荐这种方式,由于会让代码变长。
检查类的命名规则是ZCL_ADV_类型名_CHECK。
为了便于使用,方法is_valid的定义十分简单,只有一个输入参数、一个返回值,不包含任何异常,这使得它没法胜任数量、金额等类型(通常而言是P类型,包含长度和小数位定义)字段的检查。为了解决这一问题,ABAP Data Validator提供了参考数据元素进行检查的用法。可使用类zcl_adata_validator的方法validate_by_element使用该功能,示例以下,
DATA(result) = NEW zcl_adata_validator( )->->validate_by_element( data = data element = 'MENGE_D' "数量 ).
result是一个结构,包含两个字段valid和type,若是data的值没法转换为数字、或者转换后溢出的话,result-valid将被赋值为abap_false(即空);若是data是一个有效值,那么rresult-valid将被赋值为abap_true(即'X')。
正常状况下,result-type总会被赋值为数据元素的类型,对P类型,则为固定值’PACKED‘(c_type_packed)。但若是输入的数据元素无效的话,type则会被赋值为固定值’Invalid Type‘(c_type_invalid)。
目前支持如下类型的数据元素:
为了保持检查方法的简单性,validate_by_element方法的定义一样不包含异常。任何异常都会在方法内部被处理。出现异常时,result-valid会被赋值为abap_false,type会被赋值为’Invalid Type‘。
ABAP Data Validator能够根据指定的规则对内表进行检查,以下所示,将规则my_rules和内表uploaded_data传入类zcl_adata_validator的方法validate,能够获得检查结果内表results,
TRY. DATA(results) = NEW zcl_adata_validator( )->validate( rules = my_rules data = uploaded_data ). CATCH zcx_adv_exception INTO DATA(ex). DATA(msg) = ex->get_text( ). ENDTRY.
检查规则rules用于设定检查逻辑。
rules的类型定义以下,
TYPES: BEGIN OF ty_rule, fname TYPE name_komp, "字段名 required TYPE abap_bool, "必填 initial_or_empty TYPE abap_bool, "必须为空或初始值 user_type TYPE ty_spec_type,"检查类型(参考类zcl_adata_validator的常量列表) regex TYPE string, "自定义正则表达式 regex_msg TYPE string, "自定义正则表达式检查失败消息 ref_element TYPE rollname, "参考数据元素 END OF ty_rule. TYPES: ty_rules_t TYPE HASHED TABLE OF ty_rule WITH UNIQUE KEY fname.
简单的示例以下,
DATA: rules TYPE zcl_adata_validator=>ty_rules_t. *字段1为必填字段,类型是日期,字段2非必填,类型为邮件地址 rules = VALUE #( ( fname = 'FIELD1' required = abap_true user_type = zcl_adata_validator=>c_type_date ) ( fname = 'FIELD2' user_type = zcl_adata_validator=>c_type_email ) ).
使用ABAP Data Validator自带的检查逻辑能够知足不少场景下的基本检查须要,可是你也许还有更多的检查逻辑。有2种方式能够实现检查功能的扩展。
正则表达式示例:若是你不只要检查一个字段的值是否为邮件地址,还要验证它是gmail邮箱,那么能够把正则表达式’gmail\.com$‘复制给rules-regex,
DATA: rules TYPE zcl_adata_validator=>ty_rules_t. DATA: cases TYPE ty_case_t. cases = VALUE #( ( field3 = 'ZZZ2@gmail.com') "正确,是gmail邮箱 ( field3 = 'ZZZ2@qq.com') "不正确,非gmail邮箱 ). rules = VALUE #( ( fname = 'FIELD2' user_type = zcl_adata_validator=>c_type_email regex = 'gmail\.com$' regex_msg = 'Only gmail supported') ).
或者建立一个新类型和它的检查类,而且把它的检查类配置传入constructor,
DATA: check_class_config TYPE zcl_adata_validator=>ty_check_config_t. check_class_config = VALUE #( ( type = zcl_adata_validator=>c_type_new class = 'ZCL_NEW_VALIDATOR' ) ). TRY. DATA(result) = NEW zcl_adata_validator( check_class_conifg = check_class_config )->validate( rules = rules data = cases ). CATCH zcx_adv_exception INTO DATA(ex). DATA(msg) = ex->get_text( ). ENDTRY.
注意:constructor中已经包含了默认的检查类配置和检查消息配置,它们是Hard coding,一旦传入自定义配置,它们就会被覆盖。
能够按需对方法进行重定义、或者传入本身的配置。好比,从数据库或其它来源读取配置,这样能够在不修改既有代码的状况下扩展程序的功能。
DATA: check_class_config TYPE zcl_adata_validator=>ty_check_config_t. SELECT * FROM my_config_table INTO TABLE @check_class_config. TRY. DATA(result) = NEW zcl_adata_validator( check_class_conifg = check_class_config )->validate( rules = rules data = cases ). CATCH zcx_adv_exception INTO DATA(ex). DATA(msg) = ex->get_text( ). ENDTRY.
https://github.com/hhelibeb/abap-data-validator
我提交了绝大部分代码,此外还有2位贡献者larshp和FreHu,他们帮助修正了代码格式和readme方面的一些问题。
欢迎参与这个工具的开发!若是你发现程序有任何问题,也能够在github提交issue告知我。
有效性的定义十分重要,若是有效的定义是模糊的,那检查也失去了意义。
对于ABAP Data Validator,若是一个检查类型存在对应的ABAP数据类型(好比日期,时间戳等),那么“有效”是指:
以时间戳为例,
2021-12-21 00:00:00’\可能在某些情境下是合理的时间戳值,可是对于ABAP Data Validator而言,它是无效的,由于将它赋值给时间戳类型的变量会致使dump。而'19000000235959'虽然能够被赋值给ABAP时间戳变量,但由于没有实际意义,它一样是无效值。
这种类型检查的逻辑主要由SAP提供的标准功能实现,时间戳的检查实际上由正则检查、标准函数DATE_CHECK_PLAUSIBILITY和TIME_CHECK_PLAUSIBILITY组成。
若是一个检查类型没有对应的ABAP数据类型,ABAP Data Validator的检查逻辑收集自一些相对权威的来源,这些检查逻辑一般会符合行业标准。来源包括,
绝大部分检查逻辑是成熟的,且它们都包含单元测试。你能够在单元测试中加上本身的用例来验证它们的行为是否符合你的指望。
HTML检查是个例外,它是惟一一个须要调用外部API(https://validator.w3.org/)的检查,并且w3.org提供的API自己也只是实验性的。请只把它的检查结果看成参考。
目前,我已经在工做中部分地应用了ABAP Data Validator,看起来工做良好。