• EMF学习,为了实现可扩展可自定义的模型验证


    自:

      http://blog.csdn.net/javaman_chen/article/details/6057033

      http://www.ibm.com/developerworks/cn/opensource/os-cn-ecl-emfvldt/

      http://blog.csdn.net/james999/article/details/1624747

    EMF Validation Framework 提供了对 EMF eObjects 的校验框架,和 EMF EValidator API 相比它能提供更复杂全面的验证并且易用易扩展。EMF Validation Framework 提供了灵活的验证定义方式,支持两种验证触发机制:Batch 和 Live。它支持用 JAVA 和 OCL 语言来实现约束,此外它还支持自定义验证时的模型扫描算法,并提供了一个 Validation Client Context 来规避不必要的验证。

    EMF模型的验证主要通过ModeValidationService类的调用来完成,该类还声明了一个工厂方法newValidator()用于获取IValidator的实现类。IValidator执行器会从Validation Service模块中获取所匹配的Constraint进行验证。IValidator的子接口有两个,分别是ILiveValidator和IBatchValidator,对应模型的验证方式是Live模式还是Batch模式;而模式的区分通过EvaluationMode来指定。

    验证整体需要以下几步:

    1.构建约束。

    2.注入验证环境

    3.将约束与Application进行绑定

    4.书写验证主体

    1.  构建约束

    目前支持三种方式:Java Code,EMF Model,以及OCL。所有的约束必须实现 IModelConstraint 接口,定义了验证执行的逻辑(validate()),并拥有一个约束描述符(一个实现 IConstraintDescriptor 接口的类),该描述符包含了这个约束的源信息,例如,验证模式是 live 还是 batch,验证的目标对象等。不同的Constraint Model类型下会有不同的实现。因为Validation Framework这套构架依赖于在plugin.xml中描述和申明来注册相应的constrain实现,所以需要不同的Parser负责解析和管理。

    1.1 java方式。约束的构建主要通过继承AbstractModelConstraint抽象类来完成。AbstractModelConstraint使用了IValidationContext接口作为validate()的方法参数,并且返回Istatus对象用来封装验证结果。//validate(IValidationContext ctx)

    IValidationContext对象

    (1)提供了当前验证环境的相关信息,包括:
      target:所验证的目标对象;
      eventType:表示Live模式下触发验证操作的事件;
      currentConstraintId:当前所执行的约束Id,等等...

    (2) 提供了一些提高验证效率的方法,例如可以用来指定一些的目标对象是“合格的”可以不执行某些验证方法,缓存验证对象。

    在validate方法中,如果约束得评估没有通过,可调用IValidationContext接口定义的createFailureStatus(Object... args)方法返回错误状态类型相反,如果评估成功,可调用createSuccessStatus()方法返回成功状态类型。

    1.2 OCL

    使用EMF OCL非常简单,使用QueryFactory构造一个Query对象,设置表达式(Express),以及表达式所依赖的Context(在EMF OCL中,一般是Classifier)。然后对给定eObject对象进行检查和计算。——就这么简单。
     
    Query query = QueryFactory.eINSTANCE.createQuery(
        "Book.allInstances()->select(b : Book | b <> self and b.title = self.title)",
        LibraryPackage.eINSTANCE.getBook());
    query.setExtentMap(extents);
    Collection result = query.evaluate(myBook);

    2. 注入验证环境

    通过实现org.eclipse.emf.validation.constraintProviders扩展点完成约束的注入。

    3.与Application进行绑定

    通过org.eclipse.emf.validation.constraintBindings扩展点来实现该功能。

    只能在EclipseRCP环境下运行,而且编写扩展点的实现也非常的繁琐。

    4.书写验证主题,参照验证逻辑变下

    Batch的验证逻辑为:

    1. 指定验证对象,可以使一个EObject或其集合  List objects = myResource.getContents();
    2. 通过验证服务ModelValidationService构建IBatchValidator  
    3. 通过EvaluationMode.BATCH指明为Batch模式                                                                                                                                                        IValidator validator = ModelValidationService.getInstance().newValidator(EvaluationMode.BATCH);  
    4. validator.setIncludeLiveConstraints(true);//包含Live模式的约束  验证约束这里不需要指定,因为后面的验证是需要注册如application的,而不是添加,而约束可以通过过滤器设置,这里使得验证很难灵活的在使用中添加新的约束。
    5. //可以添加约束的过滤设置   validate.addConstraintFilter(new IConstraintFilter() {...  
    6. 模型的验证返回IStatus对象 IStatus results = validator.validate(objects);  
    7. 判断验证状态  if (!results.isOK()) {ErrorDialog.openError(null, "Validation", "Validation Failed", results); }  

    另一种方式//只是替换现成的Validator的实现

    用户还可自己编写EValidator的实现,然后将该实现类注入到EValidator注册表中去,一样可完成模型验证操作,
    且这种方式无需编写扩展点的实现,因此只需要OSGI环境就可以了。

    1. 编写EValidator的实现

    (1)若直接在模型中指明了约束,可以通过*.genmodel文件,是可以直接生成对应的EValidator实现类的。

    2. 添加到EValdator注册表中

    对应代码

    3. 编写模型的验证代码

    1. 设置验证目标对象 Object target=getTartget();
    2. Diagnostician diagnostician=new Diagnostician();  
    3. BasicDiagnostic diagnostic=diagnostician.createDefaultDiagnostic(target);  
    4. Map<Object, Object> context = diagnostician.createDefaultContext();  
    5. 执行验证操作 diagnostician.validate(library, diagnostic, context);

    评估:

    有两点可能阻碍实现可扩展、可自定义的验证:

    1. 不仅仅需要验证逻辑的实现,而且需要注册,设置扩展点能操作来具体的配置约束,可不能随意添加自定义的约束

    2. 每条约束对应一段代码,如何添加自定义的验证需要思考,这里可以参考OCL验证引擎的实现,北大硕士论文

  • 相关阅读:
    Python菜鸟之路:Python基础-线程、进程、协程
    Python菜鸟之路:Python基础-Socket编程-2
    Python菜鸟之路:Python基础-Socket基础-1
    react-native 使用 antd-mobile-rn UI进行开发app
    Java基础
    Java基础
    Java基础
    Java基础
    Java基础
    Java基础
  • 原文地址:https://www.cnblogs.com/fireflyupup/p/4859677.html
Copyright © 2020-2023  润新知