Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » OCL » How to define cross-referenced custom operations(How to define two custom operations A and B such that A calls B and B calls A)
How to define cross-referenced custom operations [message #758709] Thu, 24 November 2011 10:56 Go to next message
David Aguilera is currently offline David AguileraFriend
Messages: 3
Registered: March 2010
Junior Member
Hi folks!

I'm currently working on a project that evaluates some OCL queries over a UML schema. My OCL expressions are defined over the UML metamodel. For example, I would like to check whether a Class c has its name n capitalized, so I write the following code:
org.eclipse.uml2.uml.Class c = null; // Suppose I have the Class c

OCL ocl = OCL.newInstance();
Helper helper = ocl.createOCLHelper();

helper.setContext(c.eClass());
// I defined the custom operation "String::at(position:Integer) : Integer"
String expression = "self.name.at(1) = self.name.at(1).toUpper()";
Query query = ocl.createQuery(helper.createQuery(expression));
Boolean result = (Boolean)query.evaluate(c);
which works properly.

The expressions I work with are far more complex than that. In order to reduce the amount of OCL code I have to write, I want define custom operations using the "helper.defineOperation()" mechanism:
// ...
helper.defineOperation("A() : Boolean = true");


Once an operation A has been defined, a new operation B may use the operation A:
// ...
helper.defineOperation("B() : Boolean = self.A()");


It is obvious that I have to define A before B, since B requires A. If I first define B, I get a SemanticException stating that operation A cannot be found.

My problem is I have a cycle of invokations: A requires B, and B requires A:
// ...
helper.setContext(c.eClass());
helper.defineOperation("A() : Boolean = " +
   "if self.name = 'Person' then " + // Random condition :P
   "   self.B() " +
   "else " +
   "   true " +
   "endif");
helper.defineOperation("B() : Boolean = " +
   "if self.ownedAttribute->size() > 2 then " + // Random condition :P
   "   false " +
   "else " +
   "   self.A() " +
   "endif");


I know this scenario, where A may call B and B may call A, may result in in an endless loop... but the code is supposed to be more "clever" than this example, and the execution should not enter an endless loop. Anyway, my problem is previous to the execution stage: I cannot define operations A nor B because each one depends on each other.

I don't know how to solve this problem... is there any mechanism to first define operation signatures and then their bodies?

I know I could define these operations in Java (creating a custom EcoreEnvironment and so on), but I don't want to use it: I need the operations to be defined by means of OCL expressions only, without Java code.

I hope you can help me, guys.
Thank you!

-- David
Re: How to define cross-referenced custom operations [message #758875 is a reply to message #758709] Thu, 24 November 2011 21:49 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 4153
Registered: July 2009
Senior Member
Hi David

Direct programming of OCL in Java is for real enthusiasts/total nutcases.

Have you looked at the OCLinEcore tutorial?

Have you considered using a Complete OCL document?

Both of these approaches will give you a syntax and semantics checking
editor.

As from Juno M4 (or the current N-build) there is a Direct OCL to Java
code generator so that the java is generated automatically; not quite as
fast as you might do by hand, but all parsing occurs at compile time, so
you're likely to experience a significant net speed up.

Regards

Ed Willink

On 24/11/2011 10:56, David Aguilera wrote:
> Hi folks!
>
> I'm currently working on a project that evaluates some OCL queries
> over a UML schema. My OCL expressions are defined over the UML
> metamodel. For example, I would like to check whether a Class c has
> its name n capitalized, so I write the following code:
>
> org.eclipse.uml2.uml.Class c = null; // Suppose I have the Class c
>
> OCL ocl = OCL.newInstance();
> Helper helper = ocl.createOCLHelper();
>
> helper.setContext(c.eClass());
> // I defined the custom operation "String::at(position:Integer) :
> Integer"
> String expression = "self.name.at(1) = self.name.at(1).toUpper()";
> Query query = ocl.createQuery(helper.createQuery(expression));
> Boolean result = (Boolean)query.evaluate(c);
> which works properly.
>
> The expressions I work with are far more complex than that. In order
> to reduce the amount of OCL code I have to write, I want define custom
> operations using the "helper.defineOperation()" mechanism:
>
> // ...
> helper.defineOperation("A() : Boolean = true");
>
>
> Once an operation A has been defined, a new operation B may use the
> operation A:
>
> // ...
> helper.defineOperation("B() : Boolean = self.A()");
>
>
> It is obvious that I have to define A before B, since B requires A. If
> I first define B, I get a SemanticException stating that operation A
> cannot be found.
>
> My problem is I have a cycle of invokations: A requires B, and B
> requires A:
>
> // ...
> helper.setContext(c.eClass());
> helper.defineOperation("A() : Boolean = " +
> "if self.name = 'Person' then " + // Random condition :P
> " self.B() " +
> "else " +
> " true " +
> "endif");
> helper.defineOperation("B() : Boolean = " +
> "if self.ownedAttribute->size() > 2 then " + // Random condition :P
> " false " +
> "else " +
> " self.A() " +
> "endif");
>
>
> I know this scenario, where A may call B and B may call A, may result
> in in an endless loop... but the code is supposed to be more "clever"
> than this example, and the execution should not enter an endless loop.
> Anyway, my problem is previous to the execution stage: I cannot define
> operations A nor B because each one depends on each other.
>
> I don't know how to solve this problem... is there any mechanism to
> first define operation signatures and then their bodies?
>
> I know I could define these operations in Java (creating a custom
> EcoreEnvironment and so on), but I don't want to use it: I need the
> operations to be defined by means of OCL expressions only, without
> Java code.
>
> I hope you can help me, guys.
> Thank you!
>
> -- David
Re: How to define cross-referenced custom operations [message #759407 is a reply to message #758875] Mon, 28 November 2011 15:22 Go to previous messageGo to next message
David Aguilera is currently offline David AguileraFriend
Messages: 3
Registered: March 2010
Junior Member
Hi Edward,

First of all, thank you for your reply. I looked at the OCLinEcore tutorial, as you suggested, but it is not (exactly) what I am looking for. I was able to create an OCL document (example.ocl) with the following content*:

package uml

context Class
def: A() : String =
   self.B()
   
context Class
def: B() : String =
   self.A()

endpackage

using the CompleteOCL Editor. Thanks to this editor, I had syntax highlighting and parsing exceptions. Within the editor, the behavior is the one I originally expected: I get an "Unresolved operation B()" error while writing the first operation A, but it only lasts until I define the second operation (B).

The problems arise when I want to load these operations into my Java code. Either if I load them from an OCLInput document (using "ocl.parse(document)") or if I load them as my original post stated ("helper.defineOperation(...)"), I get a SemanticException:

Exception in thread "main" org.eclipse.ocl.SemanticException: Cannot find operation (B()) for the type (Class)
   at org.eclipse.ocl.util.OCLUtil.checkForErrors(OCLUtil.java:352)
   at org.eclipse.ocl.OCL.parse(OCL.java:323)
   ...


I think I did not make myself clear in the previous post, so let's state my goals properly: I'm writing a Java program whose purpose is to evaluate a set of queries over a UML model, and return the evaluation results to the modeler/user. It is important to keep in mind that these queries have to be defined in OCL and some queries require helper operations.

I'm having problems with the definition of these additional helper operations. Some of these helper operations are defined in Java (like, for example, the "regexMatch" operation), whilst others are defined in OCL. My problem is, again, how to define a couple of helper operations A and B in OCL such that A requires B and B requires A.

I think that what I'm looking for is something like a "lazy parsing (?)" (I don't know if this is the proper term). I would like the parser to successfully parse an operation A, even if A requires an operation B that does not exist yet. Why? Because I can assure that B will exist when A is invoked.

I hope we can finally get rid of this problem.

Best regards,
David


* I was only able to select the "ocl" package in the CompleteOCL Editor. I was unable to load the "ecore" or "uml" packages to define additional operations in their metamodels.
** I know the example would end up in an endless loop
Re: How to define cross-referenced custom operations [message #759466 is a reply to message #759407] Mon, 28 November 2011 18:51 Go to previous message
Ed Willink is currently offline Ed WillinkFriend
Messages: 4153
Registered: July 2009
Senior Member
Hi David

Ok. I see your problem now. The old Eclipse OCL has a forward
referencing 'feature'
(https://bugs.eclipse.org/bugs/show_bug.cgi?id=187679), for which the
specification is not sufficiently clear to make it bug. But of course
when you fall foul of a 'feature', it seems like a bug. The old Eclipse
OCL requires quite a bit of enthusiasm to add Java extensions. See
org.eclipse.ocl.ecore.tests.EcoreEnvironmentTest for a regex example.

The new Eclipse OCL, of which the editor is a part, permits forward and
backward references. But the new Eclipse OCL is experimental; in
examples packages. The new Eclipse OCL has a modelled library so you can
easily add your own Java feature implementations. See
/org.eclipse.ocl.examples.library/model/OCL-2.4.oclstdlib for a library
definition and
org.eclipse.ocl.examples.test.xtext.OCLstdlibTests.testLoadAsString for
a custom library usage.

Regards

Ed Willink

On 28/11/2011 15:22, David Aguilera wrote:
> Hi Edward,
>
> First of all, thank you for your reply. I looked at the OCLinEcore
> tutorial, as you suggested, but it is not (exactly) what I am looking
> for. I was able to create an OCL document (example.ocl) with the
> following content*:
>
>
> package uml
>
> context Class
> def: A() : String =
> self.B()
> context Class
> def: B() : String =
> self.A()
>
> endpackage
>
> using the CompleteOCL Editor. Thanks to this editor, I had syntax
> highlighting and parsing exceptions. Within the editor, the behavior
> is the one I originally expected: I get an "Unresolved operation B()"
> error while writing the first operation A, but it only lasts until I
> define the second operation (B).
>
> The problems arise when I want to load these operations into my Java
> code. Either if I load them from an OCLInput document (using
> "ocl.parse(document)") or if I load them as my original post stated
> ("helper.defineOperation(...)"), I get a SemanticException:
>
>
> Exception in thread "main" org.eclipse.ocl.SemanticException: Cannot
> find operation (B()) for the type (Class)
> at org.eclipse.ocl.util.OCLUtil.checkForErrors(OCLUtil.java:352)
> at org.eclipse.ocl.OCL.parse(OCL.java:323)
> ...
>
>
> I think I did not make myself clear in the previous post, so let's
> state my goals properly: I'm writing a Java program whose purpose is
> to evaluate a set of queries over a UML model, and return the
> evaluation results to the modeler/user. It is important to keep in
> mind that these queries have to be defined in OCL and some queries
> require helper operations.
>
> I'm having problems with the definition of these additional helper
> operations. Some of these helper operations are defined in Java (like,
> for example, the "regexMatch" operation), whilst others are defined in
> OCL. My problem is, again, how to define a couple of helper operations
> A and B in OCL such that A requires B and B requires A.
>
> I think that what I'm looking for is something like a "lazy parsing
> (?)" (I don't know if this is the proper term). I would like the
> parser to successfully parse an operation A, even if A requires an
> operation B that does not exist yet. Why? Because I can assure that B
> will exist when A is invoked.
>
> I hope we can finally get rid of this problem.
>
> Best regards,
> David
>
>
> * I was only able to select the "ocl" package in the CompleteOCL
> Editor. I was unable to load the "ecore" or "uml" packages to define
> additional operations in their metamodels.
> ** I know the example would end up in an endless loop
Previous Topic:How to initialize the attributes of variables in an OCL query
Next Topic:Comments in OCLInput
Goto Forum:
  


Current Time: Wed Nov 26 03:22:26 GMT 2014

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

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