ClassCastException thrown when using ecore::EDouble [message #1067896] |
Thu, 11 July 2013 07:36 |
Cedric Moonen Messages: 274 Registered: August 2009 |
Senior Member |
|
|
Hi Ed,
I have a very simple ecore model (the full project with the genmodel is in attachment too):
import ecore : 'http://www.eclipse.org/emf/2002/Ecore#/';
package components : components = 'http://components/1.0'
{
class Container
{
attribute requiredWeight : ecore::EDouble;
attribute actualWeight : ecore::EDouble { derived readonly transient volatile }
{
derivation: components.weight
->sum();
}
property components#parentContainer : Component[*] { ordered composes };
invariant validWeight('The actual weight exceeds the required weight'): if actualWeight > requiredWeight
then null
else true
endif;
}
class Component
{
property parentContainer#components : Container;
attribute weight : ecore::EDouble;
}
}
When I generate Java code for this example, I see that the generated getActualWeight method of the Container class looks like this:
public double getActualWeight() {
/**
* components.weight->sum()
*/
final /*@NonNull*/ /*@NonInvalid*/ components.Container self = this;
final /*@NonNull*/ /*@NonInvalid*/ DomainEvaluator evaluator = new EcoreExecutorManager(this, ComponentsTables.LIBRARY);
final /*@NonNull*/ /*@NonInvalid*/ IdResolver idResolver = evaluator.getIdResolver();
final /*@NonNull*/ /*@Thrown*/ List<?> components = self.getComponents();
final /*@NonNull*/ /*@Thrown*/ OrderedSetValue BOXED_components = idResolver.createOrderedSetOfAll(ComponentsTables.ORD_CLSSid_Component, components);
/*@NonNull*/ /*@NonInvalid*/ SequenceValue.Accumulator accumulator = ValuesUtil.createSequenceAccumulatorValue(ComponentsTables.SEQ_PRIMid_Real);
/*@Nullable*/ Iterator<?> ITERATOR__1 = BOXED_components.iterator();
/*@NonNull*/ /*@Thrown*/ SequenceValue collect;
while (true) {
if (!ITERATOR__1.hasNext()) {
collect = accumulator;
break;
}
/*@Nullable*/ /*@NonInvalid*/ Component _1 = (Component)ITERATOR__1.next();
/**
* weight
*/
if (_1 == null) {
throw new InvalidValueException("Null source");
}
final /*@NonNull*/ /*@Thrown*/ Number weight = _1.getWeight();
final /*@NonNull*/ /*@Thrown*/ RealValue BOXED_weight = ValuesUtil.realValueOf(weight);
//
accumulator.add(BOXED_weight);
}
final /*@NonNull*/ /*@Thrown*/ RealValue sum = (RealValue)CollectionSumOperation.INSTANCE.evaluate(evaluator, TypeId.REAL, collect);
final /*@NonNull*/ /*@Thrown*/ Number UNBOXED_sum = sum.asNumber();
return (Double)UNBOXED_sum;
}
The last line is wrong (the cast) and will produce a ClassCastException when an instance of the model is validated (or when the property view is retrieving the value of actualWeight, but this is internally ignored, instead the value is simply not visible). This problem also occurs when generating Delegates instead of Java code for OCL constraints.
The last line should in fact be:
return UNBOXED_sum.doubleValue();
I have some other code which is similar (a method body which is also supposed to return an ecore::EDouble) for which this is generated properly, so I think this is very specific to the scenario that I'm having here.
Any idea what might cause the problem ?
Thanks,
Cédric
|
|
|
Re: ClassCastException thrown when using ecore::EDouble [message #1067910 is a reply to message #1067896] |
Thu, 11 July 2013 08:34 |
Ed Willink Messages: 7655 Registered: July 2009 |
Senior Member |
|
|
Hi
When you have such a good repro, please raise a Bugzilla.
Regards
Ed Willink
On 11/07/2013 08:36, Cedric Moonen wrote:
> Hi Ed,
>
> I have a very simple ecore model (the full project with the genmodel is in attachment too):
>
> import ecore : 'http://www.eclipse.org/emf/2002/Ecore#/';
>
> package components : components = 'http://components/1.0'
> {
> class Container
> {
> attribute requiredWeight : ecore::EDouble;
> attribute actualWeight : ecore::EDouble { derived readonly transient volatile }
> {
> derivation: components.weight
> ->sum();
> }
>
> property components#parentContainer : Component[*] { ordered composes };
>
> invariant validWeight('The actual weight exceeds the required weight'): if actualWeight> requiredWeight
> then null
> else true
> endif;
>
> }
>
> class Component
> {
> property parentContainer#components : Container;
> attribute weight : ecore::EDouble;
> }
>
> }
>
> When I generate Java code for this example, I see that the generated getActualWeight method of the Container class looks like this:
>
> public double getActualWeight() {
> /**
> * components.weight->sum()
> */
> final /*@NonNull*/ /*@NonInvalid*/ components.Container self = this;
> final /*@NonNull*/ /*@NonInvalid*/ DomainEvaluator evaluator = new EcoreExecutorManager(this, ComponentsTables.LIBRARY);
> final /*@NonNull*/ /*@NonInvalid*/ IdResolver idResolver = evaluator.getIdResolver();
> final /*@NonNull*/ /*@Thrown*/ List<?> components = self.getComponents();
> final /*@NonNull*/ /*@Thrown*/ OrderedSetValue BOXED_components = idResolver.createOrderedSetOfAll(ComponentsTables.ORD_CLSSid_Component, components);
> /*@NonNull*/ /*@NonInvalid*/ SequenceValue.Accumulator accumulator = ValuesUtil.createSequenceAccumulatorValue(ComponentsTables.SEQ_PRIMid_Real);
> /*@Nullable*/ Iterator<?> ITERATOR__1 = BOXED_components.iterator();
> /*@NonNull*/ /*@Thrown*/ SequenceValue collect;
> while (true) {
> if (!ITERATOR__1.hasNext()) {
> collect = accumulator;
> break;
> }
> /*@Nullable*/ /*@NonInvalid*/ Component _1 = (Component)ITERATOR__1.next();
> /**
> * weight
> */
> if (_1 == null) {
> throw new InvalidValueException("Null source");
> }
> final /*@NonNull*/ /*@Thrown*/ Number weight = _1.getWeight();
> final /*@NonNull*/ /*@Thrown*/ RealValue BOXED_weight = ValuesUtil.realValueOf(weight);
> //
> accumulator.add(BOXED_weight);
> }
> final /*@NonNull*/ /*@Thrown*/ RealValue sum = (RealValue)CollectionSumOperation.INSTANCE.evaluate(evaluator, TypeId.REAL, collect);
> final /*@NonNull*/ /*@Thrown*/ Number UNBOXED_sum = sum.asNumber();
> return (Double)UNBOXED_sum;
> }
>
> The last line is wrong (the cast) and will produce a ClassCastException when an instance of the model is validated (or when the property view is retrieving the value of actualWeight, but this is internally ignored, instead the value is simply not visible). This problem also occurs when generating Delegates instead of Java code for OCL constraints.
>
> The last line should in fact be:
> return UNBOXED_sum.doubleValue();
>
> I have some other code which is similar (a method body which is also supposed to return an ecore::EDouble) for which this is generated properly, so I think this is very specific to the scenario that I'm having here.
>
> Any idea what might cause the problem ?
> Thanks,
> Cédric
|
|
|
|
Powered by
FUDForum. Page generated in 0.02889 seconds