EMF學習,爲了實現可擴展可自定義的模型驗證 - 各類實現方法學習

自:java

  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/1624747app

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來指定。eclipse

驗證總體須要如下幾步:ide

1.構建約束。lua

2.注入驗證環境spa

3.將約束與Application進行綁定.net

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驗證引擎的實現,北大碩士論文

相關文章
相關標籤/搜索