• EMF介绍系列(八、模型的验证)


    在ecore模型里可以详细的定义各种类型、属性和方法,但对于像“每个类别里至少有两种产品”这样的限制就无能为力了。为此,EMF提供了一套验证框架(Validator Framework)用于解决这个问题,在ecore文件里特定的方法可以被识别为验证方法并生成用于验证的代码。

    还是以shop模型为例,假设要求“每个类别里至少有两种产品”,我们需要在shop.ecore里添加一个名为“validateProductsCount”的验证方法,如图1所示。验证方法的返回类型是要具有两个参数:第一个是EDiagnosticChain类型,第二个是EMap类型,参数的名称没有特别要求,但这两个参数的顺序不能交换。


    图1 新增的验证方法

    接下来,通过shop.genmodel重新生成一遍代码(如果还没有shop.genmodel文件,通过“New -> EMF Model”创建一个),注意没有必要reload这个genmodel文件。通过比较添加验证方法前后的代码,可以发现EMF在util包里多生成了一个名为ShopValidator.java的文件;同时,在CategoryImpl的validateProductsCount()方法里的代码如下所示:

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated
     
    */
    public boolean validateProductsCount(DiagnosticChain diagnostics, Map contex) {
        
    // TODO: implement this method
        
    // -> specify the condition that violates the invariant
        
    // -> verify the details of the diagnostic, including severity and message
        
    // Ensure that you remove @generated or mark it @generated NOT
        if (false) {
            
    if (diagnostics != null) {
                diagnostics.add
                    (
    new BasicDiagnostic
                        (Diagnostic.ERROR,
                         ShopValidator.DIAGNOSTIC_SOURCE,
                         ShopValidator.CATEGORY__VALIDATE_PRODUCTS_COUNT,
                         EcorePlugin.INSTANCE.getString(
    "_UI_GenericInvariant_diagnostic"new Object[] { "validateProductsCount", EObjectValidator.getObjectLabel(this, contex) }),
                         
    new Object [] { this }));
            }
            
    return false;
        }
        
    return true;
    }

    有别于普通方法的实现(简单的抛出一个UnsupportedOperationException异常)。由于这段代码是被“if(false){...}”包围的,所以如果不进行定制,则里面的内容永远不会被执行,被包围代码的功能是将验证错误记录下来以便统一报告。现在,我们要做的就是修改这个条件,来告诉EMF什么时候运行里面的代码,如下所示:

    /**
     * <!-- begin-user-doc -->
     * <!-- end-user-doc -->
     * @generated NOT
     
    */
    public boolean validateProductsCount(DiagnosticChain diagnostics, Map contex) {
        
    // 我们修改了验证条件
        if (getProducts().size() < 2) {
            
    if (diagnostics != null) {
                diagnostics.add
                    (
    new BasicDiagnostic
                        (Diagnostic.ERROR,
                         ShopValidator.DIAGNOSTIC_SOURCE,
                         ShopValidator.CATEGORY__VALIDATE_PRODUCTS_COUNT,
                         EcorePlugin.INSTANCE.getString(
    "_UI_GenericInvariant_diagnostic"new Object[] { "validateProductsCount", EObjectValidator.getObjectLabel(this, contex) }),
                         
    new Object [] { this }));
            }
            
    return false;
        }
        
    return true;
    }
     

    因为我们要实现的验证条件很简单,所以代码的改动也很少,还是注意不要忘记修改注释中的@generated标记。现在可以运行我们的shop编辑器了,在一个只包含一种产品(Product)的类别(Category)上按右键,选择弹出菜单里的“Validate”命令,就会得到如图2所示的提示信息。


    图2 模型未通过验证

    通过修改代码的方式表达模型的限制条件是很直观,不过当条件又多又不确定的时候,直接在ecore文件里集中的表达这些条件也许更方便管理,而且Java代码甚至不需要重新生成和编译。Eclipse网站上的这篇文章“Implementing Model Integrity in EMF with EMFT OCL”通过自定义JET模板实现了这个功能,有兴趣的朋友不妨试试。

    下载本文工程

    补充另一种让EMF生成Validate代码的方法:在ecore模型里需要验证的EClass下建立一个EAnnotation,其source属性为“http://www.eclipse.org/emf/2002/Ecore”;然后在这个EAnnotation下建立key为“constraints”的Details Entry,value属性指定为想要的constraint名字,如果要定义多个constraint,则每个名字之间用空格分隔(格式见EcoreUtil#setConstraints()),如图3所示。这样,EMF就会在util包里生成XXXValidator.java文件,以及相应的验证方法,这些方法的代码和上面第一段嗲吗是类似的,同样需要自己修改if语句里的条件。


    图3 在ecore模型里添加EAnnotation以生成验证代码

    如果觉得本文内容有帮助:试试我开发的Android应用 应用计时折扣君推荐+1(需登录)

  • 相关阅读:
    zepto引用touch模块后,click失效
    cocos2dx中setContentSize与setDimensions在设置label显示区域上的区别
    convertToNodeSpace 与 convertToWorldSpace 的使用
    quick(3.2) UIListView扩展
    quick-cocos2d-x 游戏开发——StateMachine 状态机
    Lua学习笔记之字符串及模式匹配
    cocos2dx-3.x事件分发机制
    cocos2dx-Lua与Object的通讯机制
    cocos2dx-Lua与Java通讯机制
    Quick-cocos2dx容器层的使用
  • 原文地址:https://www.cnblogs.com/bjzhanghao/p/472607.html
Copyright © 2020-2023  润新知