Eclipse OCL 开发

OCL解析器提供了两个类用于解析ocl表达式,分别是OCLHelper和OCL:
OCLHelper接口的设计直接用于解析表达式,而OCL则作为解析的切入点。

OCL的解析首先要为其创建一个环境,如:是基于UML模型的还是基于ECore模型的。
可通过在构造函数中指定相应的EnvironmentFactory来实现,如:
OCL<?, EClassifier, ?, ?, ?, ?, ?, ?, ?, Constraint, EClass, EObject> ocl;
ocl = OCL.newInstance(EcoreEnvironmentFactory.INSTANCE);//ECore环境

在OCL类中声明了两个方法getEnvironment()和getEvaluationEnvironment()分别用于获取模型的根环境和评估环境,这两个环境是由EnvironmentFactory接口创建的。
在根环境中可以嵌套一些子环境用于定义package的命名空间,以此获取package的上下文,先看一段简单的OCL描述:
--包上下文 package Company --类上下文 context Person inv: name<>'zhangsan' --操作上下文 context Person::getCurrentSpouse() : Person pre: self.isMarried = true body: self.mariages->select( m | m.ended = false ).spouse --属性上下文 context Person::income : Integer init: parents.income->sum() * 1% -- pocket allowance endpackage

在OCL描述中,是通过上下文(context)的组织来体现层级结构的,如:
由package可以遍历到classifer的上下文;
由classifer可以遍历到方法或属性的上下文;
通过这种层级结构,由package上下文可以遍历到任何模型元件。
因此,Environment接口中的各种lookup方法主要是通过package context来进行相关的查找操作。

实例化OCL对象以后,可以通过createOCLHelper()方法来获取OCLHelper对象。
OCLHelper对象声明了大量方法用于创建OCL查询、约束。
不同的约束条件需要不同的上下文环境,setContext(),setOperationContext()和setAttributeContext()分别表示了该约束是针对classifer,operation还是attribute的。

OCLHelper<EClassifier, ?, ?, Constraint> helper = ocl.createOCLHelper(); helper.setContext(EXTLibraryPackage.Literals.LIBRARY);//设置上下文环境 Constraint constraint = helper.createInvariant(//创建约束 "books->forAll(b1, b2 | b1 <> b2 implies b1.title <> b2.title)"); OCLExpression<EClassifier> query = helper.createQuery(//创建查询 "books->collect(b : Book | b.category)->asSet()");

如上:createInvariant方法会解析约束表达式,createQuery方法会解析查询表达式,两个方法分别返回Constraint对象和OCLExpression对象。
有了查询和约束对象以后,可以使用Query对象对其评估。
Query<EClassifier, EClass, EObject> queryEval = ocl.createQuery(query);//获取查询评估对象 Query<EClassifier, EClass, EObject> constraintEval = ocl.createQuery(constraint);//获取约束评估对象 List<Library> libraries = getLibraries(); for (Library next : libraries) { if (constraintEval.check(next)) {//如果约束通过 @SuppressWarnings("unchecked") Set<BookCategory> categories = (Set<BookCategory>) queryEval.evaluate(next);//执行查询评估 System.out.printf("%s: %s%n", next.getName(), categories); } }

Query API提供了实用的方法,可以简写for循环:
for (Library next : constraintEval.select(libraries)) {
@SuppressWarnings("unchecked")
Set<BookCategory> categories = (Set<BookCategory>) queryEval.evaluate(next);
System.out.printf("%s: %s%n", next.getName(), categories);
}

现实应用中,经常将模型定义和模型约束写入不同的资源文件中以便于模型的管理。
OCL提供了相应的方法来解析约束文件,通过构造OCLInput对象。
OCL<?, EClassifier, ?, ?, ?, ?, ?, ?, ?, Constraint, EClass, EObject> ocl; ocl = OCL.newInstance(EcoreEnvironmentFactory.INSTANCE); IFile file = getWorkspaceFile("/ocl/constraints.ocl");//获取ocl约束文件 InputStream in = file.getContents(); //将解析出的约束存放到HashMap中 Map<String, Constraint> constraintMap = new HashMap<String, Constraint>(); try { OCLInput document = new OCLInput(in, file.getCharset());//构造OCLInput对象 List<Constraint> constraints = ocl.parse(input);//解析ocl文档 for (Constraint next : constraints) { constraintMap.put(next.getName(), next); OCLExpression<EClassifier> body = next.getSpecification().getBodyExpression(); System.out.printf("%s: %s%n", next.getName(), body); } } finally { in.close(); }

constraints.ocl文档内容如下:
package extlibrary context Library -- get all books with a title in a library and its branches (recursively) def: getBooks(title : String) : Set(Book) = books->select(b | b.title = title)->asSet()->union( branches.getBooks(title)) context Book -- the library containing a book def: library : Library = Library.allInstances()->any(books->includes(self)) -- book titles are unique within their library branch (and its sub-branches) inv unique_title: not library.oclIsUndefined() implies library.getBooks(title) = Set{self}) endpackage

通过上面的解析,将约束条件以Map形式存储起来,可通过约束的名字得到约束对象,如:
ocl.check(book, constraintMap.get("unique_title"));//对book对象进行title唯一的约束校验。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值