OCL basically is a query language in its own right, but sometimes it is useful
to plug conditions specified in OCL into an existing query structure based on
the EMF Model Query Framework. The org.eclipse.emf.query.ocl
plug-in provides the API to do that.
The OCL Condition
OCL is very good at specifying boolean-valued conditions, which are exactly what
a query needs to determine whether to accept an object. The
BooleanOCLCondition
class uses the MDT OCL API to parse and evaluate an OCL constraint.
[
as SVG]
The BooleanOCLCondition is a generic class, with type
parameters corresponding to the like-named parameters of the
OCL
class. The simplest way to construct one is with an OCL environment instance,
the boolean-valued OCL expression as a string, and the classifier in which
context to parse the constraint. For example, for an Ecore-based model:
// create an OCL environment for the Ecore metamodel
OCL ocl = org.eclipse.ocl.ecore.OCL.newInstance();
// create an OCL condition that matches that either are mysteries or are shorter
// than 200 pages
EObjectCondition tolerableRead = new BooleanOCLCondition<EClassifier, EClass, EObject>(
ocl.getEnvironment(),
"self.category <> BookCategory::Mystery implies self.pages < 200",
EXTLibraryPackage.Literals.BOOK);
// search the whole library system
Library mainBranch = getMainBranch();
IQueryResult result = new SELECT(new FROM(mainBranch), new WHERE(tolerableRead));
for (Object next : result) {
System.out.println("I can read " + ((Book) next).getTitle());
}
Context-Free OCL Conditions
The example above illustrate an OCL condition that is parsed in the context of
a specific classifier, namely Book. Sometimes, however,
it happens that a model has different classifiers that have like-named features
that have the same meaning, but are not defined as a single, common feature.
This may happen especially in models of heterogeneous metamodels. Consider the
case of the ENamedElement metaclass in Ecore and
NamedElement in UML. Both of these define a
name property that means the same thing, but they
are defined independently. How do we use OCL to query elements named
"MyStereotype" in a UML2 profile, which contains UML classes Ecore classes having
the same names?
We can use a context-free OCL condition. We construct a
BooleanOCLCondition without specifying a context
classifier. This causes the condition to evaluate itself on any element in
which context it parses, as it were by accident:
OCL ocl = org.eclipse.ocl.ecore.OCL.newInstance();
// create an OCL condition that looks for the name "MyStereotype"
EObjectCondition byName = new BooleanOCLCondition<EClassifier, EClass, EObject>(
ocl.getEnvironment(),
"self.name = 'MyStereotype'",
null); // no context classifier
// search a UML Profile
org.eclipse.uml2.uml.Profile profile = getMyProfile();
IQueryResult result = new SELECT(new FROM(mainBranch), new WHERE(byName));
for (Object next : result) {
if (next instanceof org.eclipse.emf.ecore.EClassifier) {
System.out.println("Found the Ecore representation: " + ((EClassifier) next).getName());
} else if (next instanceof org.eclipse.uml2.uml.Classifier) {
System.out.println("Found the UML representation: " + ((Classifier) next).getName());
} else {
System.out.println("Unexpected result: " + next);
}
}
Copyright (c) 2000, 2007 IBM Corporation and others. All Rights Reserved.