Skip to main content



      Home
Home » Modeling » OCL » Variable definitions
Variable definitions [message #21024] Sat, 28 April 2007 08:23 Go to next message
Eclipse UserFriend
Originally posted by: mike.aol.com

I am adapting my EMF model for OCL and am trying to get variable
definitions to work. In my EMF model, I have an operation that returns
multiple instances of a model element (PropertyBinding), e.g.:
PropertyBinding X.getProperties(String specName)
where the multiplicity of the return type is 0..*

When I try to define variables to correspond to various values of
specName and bind them to the result of the getProperties() operation, I
don't understand the results.

For example, here is how I am defining the variable:
vbl = ExpressionsFactory.eINSTANCE.createVariable();
vbl.setName(spec.getName());
vbl.setType(TypesPackage.eINSTANCE.getOrderedSetType());
oclEnv.addElement(spec.getName(), vbl, false);
evalEnv.add(spec.getName(), ruleBinding.getProperties(spec));

The result of ruleBinding.getProperties('isGrowable'), for example, is a
n EList of two elements. But when I evaluate this related expression:
isGrowable->size()
The result is 1.
When I evaluate the expression:
ruleBinding.getProperties('isGrowable')->size()

The result is 2.

How should I define the variables to correctly reflect their type?

I am puzzled by a related issue. I can't find a way to define a Let
expression to reflect the evaluation of the getProperties() operation.

For example:
let x : Sequence(PropertyBinding) =
ruleBinding.getProperties('isGrowable')->iterate(foobar :
PropertyBinding;
result : Sequence(PropertyBinding) = Sequence{} |
result->including(foobar))
in
x

throws an IllegalArgumentException: Init expression type does not
conform to type of variable (result).

I am using version plugin version 1.0.1 on a 3.2.2 platform.

Any help would be welcome.

Thanks,
Mike Gering
Re: Variable definitions [message #21072 is a reply to message #21024] Mon, 30 April 2007 12:15 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: cdamus.ca.ibm.com

Hi, Mike,

See some replies in-line, below.

HTH,

Christian


Mike Gering wrote:

> I am adapting my EMF model for OCL and am trying to get variable
> definitions to work. In my EMF model, I have an operation that returns
> multiple instances of a model element (PropertyBinding), e.g.:
> PropertyBinding X.getProperties(String specName)
> where the multiplicity of the return type is 0..*
>
> When I try to define variables to correspond to various values of
> specName and bind them to the result of the getProperties() operation, I
> don't understand the results.
>
> For example, here is how I am defining the variable:
> vbl = ExpressionsFactory.eINSTANCE.createVariable();
> vbl.setName(spec.getName());
> vbl.setType(TypesPackage.eINSTANCE.getOrderedSetType());
> oclEnv.addElement(spec.getName(), vbl, false);
> evalEnv.add(spec.getName(), ruleBinding.getProperties(spec));

You are setting the type of the variable to be the OrderedSet *metaclass*
from the OCL abstract syntax metamodel. What you really want is an
OrderedSet(PropertyBinding). Try this:

vbl.setType(TypesFactory.eINSTANCE.createOrderedSetType(
MyPackage.Literals.PROPERTY_BINDING);

(assuming that your EMF model is named 'My').


> The result of ruleBinding.getProperties('isGrowable'), for example, is a
> n EList of two elements. But when I evaluate this related expression:
> isGrowable->size()
> The result is 1.

Because the type is the OrderedSetType metaclass, which isn't itself a
collection type, the value is interpreted as a scalar (despite being, in
fact, an EList).


> When I evaluate the expression:
> ruleBinding.getProperties('isGrowable')->size()
>
> The result is 2.
>
> How should I define the variables to correctly reflect their type?
>
> I am puzzled by a related issue. I can't find a way to define a Let
> expression to reflect the evaluation of the getProperties() operation.
>
> For example:
> let x : Sequence(PropertyBinding) =
> ruleBinding.getProperties('isGrowable')->iterate(foobar :
> PropertyBinding;
> result : Sequence(PropertyBinding) = Sequence{} |
> result->including(foobar))
> in
> x
>
> throws an IllegalArgumentException: Init expression type does not
> conform to type of variable (result).

This looks like bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=164614
that was resolved in MDT OCL 1.1 (no help to you). To work around it in
for your particular case, try:

let x : Sequence(PropertyBinding) =
ruleBinding.getProperties('isGrowable')->asSequence()
in
x

using the standard collection-type coercion operation.


> I am using version plugin version 1.0.1 on a 3.2.2 platform.
>
> Any help would be welcome.
>
> Thanks,
> Mike Gering
Re: Variable definitions [message #21103 is a reply to message #21072] Mon, 30 April 2007 12:49 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: mike.aol.com

Thanks! I've gotten further, but not to home base yet. I can invoke my
EOperation now. I have to user OrderedSet because of an EMF bug I found:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=184707

But for reasons I don't understand, when I try to invoke this operation
with the result of a collection function, I get OclInvalid as the
result. For example:
variable foo is defined as OrderedSet.
myObj.myOperation(foo) -- works
myObj.myOperation(foo->select(value = 'x')) -- fails by returning
OclInvalid


Mike
Re: Variable definitions [message #21119 is a reply to message #21103] Mon, 30 April 2007 13:51 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: cdamus.ca.ibm.com

Hi, Mike,

That's odd. Since the result type of the select iterator in this case is
OrderedSet, I can only suppose that some run-time exception is happening
(probably in the evaluation of the select?). Try debugging from a
breakpoint in EvaluationVisitorImpl.evaluateSelectIterator(...) to see what
kind of exception you are getting.

Cheers,

Christian


Mike Gering wrote:

> Thanks! I've gotten further, but not to home base yet. I can invoke my
> EOperation now. I have to user OrderedSet because of an EMF bug I found:
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=184707
>
> But for reasons I don't understand, when I try to invoke this operation
> with the result of a collection function, I get OclInvalid as the
> result. For example:
> variable foo is defined as OrderedSet.
> myObj.myOperation(foo) -- works
> myObj.myOperation(foo->select(value = 'x')) -- fails by returning
> OclInvalid
>
>
> Mike
Re: Variable definitions [message #21133 is a reply to message #21119] Mon, 30 April 2007 14:40 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: mike.aol.com

Christian W. Damus wrote:
> That's odd. Since the result type of the select iterator in this case is
> OrderedSet, I can only suppose that some run-time exception is happening
> (probably in the evaluation of the select?). Try debugging from a
> breakpoint in EvaluationVisitorImpl.evaluateSelectIterator(...) to see what
> kind of exception you are getting.

Sure enough, there is an exception: IllegalArgumentException is being
thrown by the java.lang.reflect.Method.invoke() which is called from
visitOperationCallExp(), and here's why. The OCL evaluation result of
the select is a LinkedHashSet, but the EMF generated operation parameter
is an EList.

ruleBinding.addPropLoci(isGrowable) -- works
ruleBinding.addPropLoci(isGrowable->select(value = 'false')) -- throws
exception.

Is this a bug? If so, is there a workaround?

Thanks,
Mike
Re: Variable definitions [message #21150 is a reply to message #21133] Mon, 30 April 2007 14:59 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: cdamus.ca.ibm.com

Hi, Mike,

Are you working with MDT OCL 1.1 or 1.0? What is the run-time type of
isGrowable? I suppose it's an EList, but I wonder why it, too, isn't an
OrderedSet? (Java Linked HashSet)

This sounds like a bug: the OCL collection needs to be coerced to an EList
when passed into the EOperation. Raise a bug and we'll see about fixing
it:

https://bugs.eclipse.org/bugs/enter_bug.cgi?product=MDT& version=1.1.0&component=OCL

Thanks,

Christian


Mike Gering wrote:

> Christian W. Damus wrote:
>> That's odd. Since the result type of the select iterator in this case is
>> OrderedSet, I can only suppose that some run-time exception is happening
>> (probably in the evaluation of the select?). Try debugging from a
>> breakpoint in EvaluationVisitorImpl.evaluateSelectIterator(...) to see
>> what kind of exception you are getting.
>
> Sure enough, there is an exception: IllegalArgumentException is being
> thrown by the java.lang.reflect.Method.invoke() which is called from
> visitOperationCallExp(), and here's why. The OCL evaluation result of
> the select is a LinkedHashSet, but the EMF generated operation parameter
> is an EList.
>
> ruleBinding.addPropLoci(isGrowable) -- works
> ruleBinding.addPropLoci(isGrowable->select(value = 'false')) -- throws
> exception.
>
> Is this a bug? If so, is there a workaround?
>
> Thanks,
> Mike
Re: Variable definitions [message #21161 is a reply to message #21150] Mon, 30 April 2007 17:23 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: mike.aol.com

Christian,

I'm working with 1.0.2 because I'm constrained by the 3.2.2
platform/emf/gmf combination.

The runtime type is isGrowable is an EList -- it's generated from my
ecore model as a multi-valued parameter. OCL queries the EParameter and
maps it to an OrderedSet (because there's an EMF bug that forces the
EParameter to appear as an ordered, unique typed element). I don't know
that the EMF code generator produces anything other than an EList for
multi-value parameters. It doesn't honor isUnique = false at all.

I opened a bug report: https://bugs.eclipse.org/bugs/show_bug.cgi?id=184789

Mike
Re: Variable definitions [message #21176 is a reply to message #21161] Mon, 30 April 2007 17:45 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: cdamus.ca.ibm.com

Hi, Mike,

EMF wouldn't generate anything other than EList (or List in the case of
suppression of EMF types) anyway, so that wouldn't help.

Unfortunately, there isn't a plan for any more maintenance releases of the
MDT components (at least, not OCL).

You can work around this problem by overriding the
org.eclipse.emf.ocl.expressions.util.EvalEnvironment class's

canEvaluate(EOperation, int)
evaluate(EOperation, int, Object, Object[])

methods to replace the broken implementation of delegation to the Java
reflection API that the bottom of the
EvaluationVisitorImpl.visitOperationCall() class. Basically, implement
evaluate() to do what visitOperationCall() does, except with the OCL-to-EMF
collection conversion. Be careful to return true from canEvaluate() only
for operation codes <= zero (meaning that it is not an OCL-defined
operation, but an EOperation in your model).

Configure your org.eclipse.emf.ocl.query.Query instance with your custom
EvalEnvironment (Query.setEvaluationEnvironment method) before you use it
to evaluate your expression.

In the mean-time, we'll see about fixing this in the 1.1 stream.

HTH,

Christian



Mike Gering wrote:

> Christian,
>
> I'm working with 1.0.2 because I'm constrained by the 3.2.2
> platform/emf/gmf combination.
>
> The runtime type is isGrowable is an EList -- it's generated from my
> ecore model as a multi-valued parameter. OCL queries the EParameter and
> maps it to an OrderedSet (because there's an EMF bug that forces the
> EParameter to appear as an ordered, unique typed element). I don't know
> that the EMF code generator produces anything other than an EList for
> multi-value parameters. It doesn't honor isUnique = false at all.
>
> I opened a bug report:
> https://bugs.eclipse.org/bugs/show_bug.cgi?id=184789
>
> Mike
Re: Variable definitions [message #21190 is a reply to message #21176] Mon, 30 April 2007 20:52 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: mike.aol.com

Christian,

Very good! Following your advice, here's my workaround. It hacks any arg
which is an AbstractSet to an EList:

static class VceEvalEnvironment extends EvalEnvironment {

/* (non-Javadoc)
* @see
org.eclipse.emf.ocl.expressions.util.EvalEnvironment#canEval uate(org.eclipse.emf.ecore.EOperation,
int)
*/
public boolean canEvaluate(EOperation operation, int opcode) {
if(opcode <= 0) {
return true;
}
return super.canEvaluate(operation, opcode);
}

/* (non-Javadoc)
* @see
org.eclipse.emf.ocl.expressions.util.EvalEnvironment#evaluat e(org.eclipse.emf.ecore.EOperation,
int, java.lang.Object, java.lang.Object[])
*/
public Object evaluate(EOperation operation, int opcode, Object
target, Object[] args) throws UnsupportedOperationException {
//NOTE: Due to a bug in the mapping of OCL types to EMF, Any
AbstractSet type must be coerced into
// an EList
Object[] hackedArgs = new Object[args.length];
for(int i = 0; i < args.length; i++) {
if(args[i] instanceof AbstractSet) {
hackedArgs[i] = new BasicEList((AbstractSet) args[i]);
} else {
hackedArgs[i] = args[i];
}
}
// get java method for operation
Method method = EvaluationVisitorImpl.getJavaMethodFor(operation);

if (method == null) {
return Types.OCL_INVALID;
}

// invoke method on evaluated args
try {
Object result = method.invoke(target, hackedArgs);
return result;
} catch (Exception e) {
return Types.OCL_INVALID;
}
}
}
It seems to work. If you see a problem with this implementation, please
let me know.

Thanks again!
Mike
Re: Variable definitions [message #21205 is a reply to message #21190] Tue, 01 May 2007 08:26 Go to previous message
Eclipse UserFriend
Originally posted by: cdamus.ca.ibm.com

Hi, Mike,

Good news! I'm glad it works for you.

The only comment that I would make is to check for Collection, more
generally than for AbstractSet. The reason is that you may encounter Bags
resulting from some set operations, and the Java implementation of these is
distinct from the Set hierarchy.

Cheers,

Christian


Mike Gering wrote:

> Christian,
>
> Very good! Following your advice, here's my workaround. It hacks any arg
> which is an AbstractSet to an EList:
>
> static class VceEvalEnvironment extends EvalEnvironment {
>
> /* (non-Javadoc)
> * @see
>
org.eclipse.emf.ocl.expressions.util.EvalEnvironment#canEval uate(org.eclipse.emf.ecore.EOperation,
> int)
> */
> public boolean canEvaluate(EOperation operation, int opcode) {
> if(opcode <= 0) {
> return true;
> }
> return super.canEvaluate(operation, opcode);
> }
>
> /* (non-Javadoc)
> * @see
>
org.eclipse.emf.ocl.expressions.util.EvalEnvironment#evaluat e(org.eclipse.emf.ecore.EOperation,
> int, java.lang.Object, java.lang.Object[])
> */
> public Object evaluate(EOperation operation, int opcode, Object
> target, Object[] args) throws UnsupportedOperationException {
> //NOTE: Due to a bug in the mapping of OCL types to EMF, Any
> AbstractSet type must be coerced into
> // an EList
> Object[] hackedArgs = new Object[args.length];
> for(int i = 0; i < args.length; i++) {
> if(args[i] instanceof AbstractSet) {
> hackedArgs[i] = new BasicEList((AbstractSet) args[i]);
> } else {
> hackedArgs[i] = args[i];
> }
> }
> // get java method for operation
> Method method = EvaluationVisitorImpl.getJavaMethodFor(operation);
>
> if (method == null) {
> return Types.OCL_INVALID;
> }
>
> // invoke method on evaluated args
> try {
> Object result = method.invoke(target, hackedArgs);
> return result;
> } catch (Exception e) {
> return Types.OCL_INVALID;
> }
> }
> }
> It seems to work. If you see a problem with this implementation, please
> let me know.
>
> Thanks again!
> Mike
Previous Topic:Text Representation to UML2
Next Topic:OCL Type Conformance Error
Goto Forum:
  


Current Time: Tue Jul 22 12:07:07 EDT 2025

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

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

Back to the top