Simplify OCL query [message #915575] |
Mon, 17 September 2012 15:02 |
Missing name Missing name Messages: 17 Registered: September 2011 |
Junior Member |
|
|
Hello.
I am using programmatic OCL MDT and I have an OCL query that I would like to simplify, because right now I have to split it in two parts in order to make it work.
The query checks if a java type (TypeDeclaration) declares a static, public method (MethodDeclaration) whose return type is the same type. The thing is that the metamodel represents the Java AST so it's rather clumsy: there's a lot of type casting involved so I had to split the query in two:
First one gets all the MethodDeclarations from a TypeDeclaration:
self.bodyDeclarations->select(md : BodyDeclaration | md.oclIsKindOf(MethodDeclaration))
The resulting MethodDeclaration collection is iterated, executing the second query for every MethodDeclaration to see if it satisfies the constraint:
self.returnType.oclAsType(SimpleType).name.oclAsType(SimpleName).fullyQualifiedName = 'typeDeclarationName'
and
self.modifiers->exists(m : ExtendedModifier | m.oclAsType(Modifier)._static)
and
self.modifiers->exists(m : ExtendedModifier | m.oclAsType(Modifier).public)
The iteration stops when it finds the first match.
I would like to write a single OCL query for this, I guess it would be something like this:
self.bodyDeclarations->exists(md : BodyDeclaration | md.oclAsType(MethodDeclaration).returnType.oclAsType(SimpleType).name.oclAsType(SimpleName).fullyQualifiedName = 'typeDeclarationName'
and
md.oclAsType(MethodDeclaration).modifiers.exists(m : ExtendedModifier | m.oclAsType(Modifier)._static)
and
md.oclAsType(MethodDeclaration).modifiers.exists(m : ExtendedModifier | m.oclAsType(Modifier).public))
However, this does not return any value. I would like to know what am I doing wrong. Full code is:
checkTypeDeclaration(EObject TypeDeclaration) {
EPackage dom = EPackage.Registry.INSTANCE.getEPackage("org.amma.dsl.jdt.dom");
EClass typeDeclarationClass = (EClass) dom.getEClassifier("TypeDeclaration");
EClass methodDeclarationClass = (EClass) dom.getEClassifier("MethodDeclaration");
EClass simpleNameClass = (EClass) dom.getEClassifier("SimpleName");
OCL<?, EClassifier, ?, ?, ?, ?, ?, ?, ?, Constraint, EClass, EObject> ocl;
ocl = OCL.newInstance(EcoreEnvironmentFactory.INSTANCE);
EObject nameObj = (EObject) typeDeclaration.eGet(typeDeclarationClass.getEStructuralFeature("name"));
String name = (String) nameObj.eGet(simpleNameClass.getEStructuralFeature("fullyQualifiedName"));
OCLHelper<EClassifier, ?, ?, Constraint> helper = ocl.createOCLHelper();
helper.setContext(typeDeclarationClass);
OCLExpression<EClassifier> query = helper.createQuery("self.bodyDeclarations->exists(md : BodyDeclaration | md.oclAsType(MethodDeclaration).returnType.oclAsType(SimpleType).name.oclAsType(SimpleName).fullyQualifiedName = '" + name + "'
and
md.oclAsType(MethodDeclaration).modifiers.exists(m : ExtendedModifier | m.oclAsType(Modifier)._static)
and
md.oclAsType(MethodDeclaration).modifiers.exists(m : ExtendedModifier | m.oclAsType(Modifier).public))");
Query<EClassifier, EClass, EObject> eval = ocl.createQuery(query);
Object oclResult = eval.evaluate(typeDeclaration);
if (oclResult instanceof Boolean && ((Boolean) oclResult))
System.out.println(name);
}
Thanks in advance,
Javier.
[Updated on: Mon, 17 September 2012 15:06] Report message to a moderator
|
|
|
Re: Simplify OCL query [message #915585 is a reply to message #915575] |
Mon, 17 September 2012 15:27 |
Ed Willink Messages: 7670 Registered: July 2009 |
Senior Member |
|
|
Hi
At a quick glance it looks as if you've bypassed the oclIsKindOf and so
you hit a problem when oclAsType returns invalid for a 'bad' source.
In OCL you need to do
.... ->select(oclIsKindOf(X)).oclAsType(X)
which is a bit tedious, so the Juno release (Ecore and Pivot variants)
introduce a new operation
.... ->selectByKind(X)
Regards
Ed Willink
On 17/09/2012 16:03, Missing name Mising name wrote:
> Hello.
>
> I am using programmatic OCL MDT and I have an OCL query that I would
> like to simplify, because right now I have to split it in two parts in
> order to make it work.
>
> The query checks if a java type (TypeDeclaration) declares a static,
> public method (MethodDeclaration) whose return type is the same type.
> The thing is that the metamodel represents the Java AST so it's rather
> clumsy: there's a lot of type casting involved so I had to split the
> query in two:
>
> First one gets all the MethodDeclarations from a TypeDeclaration:
>
> self.bodyDeclarations->select(md : BodyDeclaration |
> md.oclIsKindOf(MethodDeclaration))
>
> The resulting MethodDeclaration collection is iterated, executing the
> second query for every MethodDeclaration to see if it satisfies the
> constraint:
>
> self.returnType.oclAsType(SimpleType).name.oclAsType(SimpleName).fullyQualifiedName
> = 'typeDeclarationName'
> and
> self.modifiers->exists(m : ExtendedModifier |
> m.oclAsType(Modifier)._static)
> and
> self.modifiers->exists(m : ExtendedModifier |
> m.oclAsType(Modifier).public)
>
> The iteration stops when it finds the first match.
>
> I would like to write a single OCL query for this, I guess it would be
> something like this:
>
> self.bodyDeclarations->exists(md : BodyDeclaration |
> md.oclAsType(MethodDeclaration).returnType.oclAsType(SimpleType).name.oclAsType(SimpleName).fullyQualifiedName
> = 'typeDeclarationName'
> and
> md.oclAsType(MethodDeclaration).modifiers.exists(m : ExtendedModifier
> | m.oclAsType(Modifier)._static)
> and
> md.oclAsType(MethodDeclaration).modifiers.exists(m : ExtendedModifier
> | m.oclAsType(Modifier).public))
>
> However, this does not return any value. I would like to know what am
> I doing wrong. Full code is:
>
>
> EObject nameObj = (EObject)
> typeDeclaration.eGet(typeDeclarationClass.getEStructuralFeature("name"));
>
> String name = (String) nameObj.eGet(simpleNameClass
> .getEStructuralFeature("fullyQualifiedName"));
>
> OCLHelper<EClassifier, ?, ?, Constraint> helper = ocl.createOCLHelper();
> helper.setContext(typeDeclarationClass);
>
> OCLExpression<EClassifier> query =
> helper.createQuery("self.bodyDeclarations->exists(md : BodyDeclaration
> |
> md.oclAsType(MethodDeclaration).returnType.oclAsType(SimpleType).name.oclAsType(SimpleName).fullyQualifiedName
> = '" + name + "'
> and
> md.oclAsType(MethodDeclaration).modifiers.exists(m : ExtendedModifier
> | m.oclAsType(Modifier)._static)
> and
> md.oclAsType(MethodDeclaration).modifiers.exists(m : ExtendedModifier
> | m.oclAsType(Modifier).public))");
>
> Query<EClassifier, EClass, EObject> eval = ocl.createQuery(query);
> Object oclResult = eval.evaluate(typeDeclaration);
> if (oclResult instanceof Boolean && ((Boolean) oclResult2)) {
> System.out.println(name);
> }
>
>
> Thanks in advance,
>
> Javier.
|
|
|
Re: Simplify OCL query [message #915591 is a reply to message #915585] |
Mon, 17 September 2012 15:44 |
Missing name Missing name Messages: 17 Registered: September 2011 |
Junior Member |
|
|
Hello Ed, thank you for your quick response. I have tried this:
OCLExpression<EClassifier> query = helper.createQuery("self.bodyDeclarations->select(md : BodyDeclaration | md.oclIsKindOf(MethodDeclaration).oclAsType(MethodDeclaration)
.returnType.oclIsKindOf(SimpleType).oclAsType(SimpleType).name.oclIsKindOf(SimpleName).oclAsType(SimpleName).fullyQualifiedName = '" + name + "')"
But there are no results.
[Updated on: Mon, 17 September 2012 15:44] Report message to a moderator
|
|
|
|
Re: Simplify OCL query [message #922828 is a reply to message #915575] |
Tue, 25 September 2012 11:24 |
Missing name Missing name Messages: 17 Registered: September 2011 |
Junior Member |
|
|
Hello Ed.
Now i've tried with this query:
OCLExpression<EClassifier> query = helper.createQuery("self.bodyDeclarations->exists(md : BodyDeclaration | md.oclIsKindOf(MethodDeclaration) and md.oclAsType(MethodDeclaration).returnType.oclIsKindOf(SimpleType) and md.oclAsType(MethodDeclaration).returnType.oclAsType(SimpleType).name.oclIsKindOf(SimpleName) and md.oclAsType(MethodDeclaration).returnType.oclAsType(SimpleType).name.oclAsType(SimpleName).fullyQualifiedName = '" + name + "')");
Which, as you can see, checks for type conformance before casting. However, it doesn't work since it doesn't return any result. I have already checked that there is at least one object in the queried model that satisfies the condition.
Is the "and" operation short-circuited? Because I've tried printing the query result and for most of the contexts return invalid, which should be prevented by the type casting...
[Updated on: Tue, 25 September 2012 11:30] Report message to a moderator
|
|
|
Re: Simplify OCL query [message #922857 is a reply to message #922828] |
Tue, 25 September 2012 12:02 |
Missing name Missing name Messages: 17 Registered: September 2011 |
Junior Member |
|
|
I have also tried this:
self.bodyDeclarations->exists(md : BodyDeclaration |
if md.oclIsKindOf(DOM::MethodDeclaration) then
if md.oclAsType(DOM::MethodDeclaration).returnType.oclIsKindOf(DOM::SimpleType) then
if md.oclAsType(DOM::MethodDeclaration).returnType.oclAsType(DOM::SimpleType).name.oclIsKindOf(DOM::SimpleName) then
md.oclAsType(DOM::MethodDeclaration).returnType.oclAsType(DOM::SimpleType).name.oclAsType(DOM::SimpleName).fullyQualifiedName = '" + name + '"
else
false
endif
else
false
endif
else
false
endif
)
to simulate short-circuiting but it doesn't work either.
[Updated on: Tue, 25 September 2012 12:04] Report message to a moderator
|
|
|
|
Re: Simplify OCL query [message #922954 is a reply to message #915575] |
Tue, 25 September 2012 13:39 |
Missing name Missing name Messages: 17 Registered: September 2011 |
Junior Member |
|
|
I think I've found the problem:
While this:
md.oclAsType(MethodDeclaration).returnType.oclAsType(SimpleType).name.oclIsKindOf(SimpleName)
returns true,
this:
md.oclAsType(MethodDeclaration).returnType.oclAsType(SimpleType).name.oclAsType(SimpleName)
returns invalid, which doesn't make any sense to me, since there is an IF condition that filters everything that doesn't satisfy the first one.
[Updated on: Tue, 25 September 2012 13:40] Report message to a moderator
|
|
|
|
Powered by
FUDForum. Page generated in 0.04164 seconds