Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » OCL » Simplify OCL query
Simplify OCL query [message #915575] Mon, 17 September 2012 15:02 Go to next message
Missing name Missing name is currently offline 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 Go to previous messageGo to next message
Ed Willink is currently offline Ed Willink
Messages: 4110
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 Go to previous messageGo to next message
Missing name Missing name is currently offline 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 #915726 is a reply to message #915591] Mon, 17 September 2012 21:06 Go to previous messageGo to next message
Ed Willink is currently offline Ed Willink
Messages: 4110
Registered: July 2009
Senior Member
Hi

Your expression is now not what you intended

oclIsKindOf return a Boolean that you then cast to MethodDeclaration.

Regards

Ed Willink


On 17/09/2012 16:44, Missing name Mising name wrote:
> 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.
Re: Simplify OCL query [message #922828 is a reply to message #915575] Tue, 25 September 2012 11:24 Go to previous messageGo to next message
Missing name Missing name is currently offline 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 Go to previous messageGo to next message
Missing name Missing name is currently offline 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 #922903 is a reply to message #922857] Tue, 25 September 2012 12:44 Go to previous messageGo to next message
Ed Willink is currently offline Ed Willink
Messages: 4110
Registered: July 2009
Senior Member
Hi

This is titled "Simplify OCL query", yet you seem to producing more and
more complicated failures.

Your code is close to unreadable and so it is not surprising that it
doesn't work.

You need to ensure that you can debug your queries interactively before
diving into code.

I recommend dumping your model to an XMI file so that you can use the
OCL console to practice
your queries and do partial queries to see which step is malfunctioning.

Regards

Ed Willink


On 25/09/2012 13:02, Missing name Mising name wrote:
> 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.
Re: Simplify OCL query [message #922954 is a reply to message #915575] Tue, 25 September 2012 13:39 Go to previous messageGo to next message
Missing name Missing name is currently offline 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

Re: Simplify OCL query [message #923092 is a reply to message #922954] Tue, 25 September 2012 15:38 Go to previous message
Ed Willink is currently offline Ed Willink
Messages: 4110
Registered: July 2009
Senior Member
Hi

It seems odd, but without seeing the metamodels it's hard to tell
whether any implicit collects have fooled you.

Regards

Ed Willink


On 25/09/2012 14:39, Missing name Mising name wrote:
> 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.
Previous Topic:Changing OCLinEcore editor code formatting
Next Topic:ocl contains operations over strings
Goto Forum:
  


Current Time: Fri Oct 31 07:53:42 GMT 2014

Powered by FUDForum. Page generated in 0.03843 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software