Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » OCL » Possible bug in generated code
Possible bug in generated code [message #1697076] Mon, 01 June 2015 12:42 Go to next message
Wilbert Alberts is currently offline Wilbert AlbertsFriend
Messages: 209
Registered: June 2010
Senior Member
Hi,

I created an ecore model with a derived attribute specified in OCL. I decided to generate the java implementation of the OCL derivation. When using the derived attribute as label in the default generated tree editor, a NPE occurred.

I suspect that the generated code is not correct; but I might be wrong. I added the eclipse projects (including generated code) as attachment.

The oclbug.ecore describes a Documentation concept with a derived 'id' attribute. This attribute tries to construct a string based on the 'element' that is being document and a 'key'. The id is computed according to:
if element.oclIsUndefined()
then
	if key.oclIsUndefined() then 'undefined' else key endif
else
	if key.oclIsUndefined() then element.name else element.name.concat(' - ').concat(key) endif
endif;

So I tried to guard against any undefined values of 'element' and/or 'key'. However when I try to create a Documentation instance (for which the 'element' has not been set) the NPE is thrown because the value of 'element' equals null. The generated code of the getId looks like (I highlight the line where the exception in thrown):
	public String getId() {
		/**
		 * 
		 * if element.oclIsUndefined()
		 * then if key.oclIsUndefined() then 'undefined' else key endif
		 * else
		 *   if key.oclIsUndefined()
		 *   then element.name
		 *   else element.name.concat(' - ').concat(key)
		 *   endif
		 * endif
		 */
		/*@Nullable*/ /*@Caught*/ Object CAUGHT_key_1;
		try {
		    final /*@Nullable*/ /*@Thrown*/ String key_1 = this.getKey();
		    CAUGHT_key_1 = key_1;
		}
		catch (Exception e) {
		    CAUGHT_key_1 = ValuesUtil.createInvalidValue(e);
		}
		final /*@NonInvalid*/ boolean symbol_3 = (CAUGHT_key_1 == null) || (CAUGHT_key_1 instanceof InvalidValueException);
		/*@NonNull*/ /*@Caught*/ Object CAUGHT_element;
		try {
		    final /*@NonNull*/ /*@Thrown*/ NamedElement element = this.getElement();
		    CAUGHT_element = element;
		}
		catch (Exception e) {
		    CAUGHT_element = ValuesUtil.createInvalidValue(e);
		}
		final /*@NonInvalid*/ boolean symbol_0 = CAUGHT_element instanceof InvalidValueException;
		/*@Nullable*/ /*@Thrown*/ String symbol_5;
		if (symbol_0) {
		    /*@Nullable*/ /*@Thrown*/ String symbol_2;
		    if (symbol_3) {
		        symbol_2 = OclbugTables.STR_undefined;
		    }
		    else {
		        final /*@Nullable*/ /*@Thrown*/ String key_0 = this.getKey();
		        symbol_2 = key_0;
		    }
		    symbol_5 = symbol_2;
		}
		else {
		    final /*@NonNull*/ /*@Thrown*/ NamedElement element_0 = this.getElement();
		    // Exception in next line //////////////////////////////////////////////////////////////////// 
		    final /*@Nullable*/ /*@Thrown*/ String name = element_0.getName();
		    //////////////////////////////////////////////////////////////////////////////////////////////////  
		    /*@Nullable*/ /*@Thrown*/ String symbol_4;
		    if (symbol_3) {
		        symbol_4 = name;
		    }
		    else {
		        final /*@NonNull*/ /*@Thrown*/ String concat = DomainUtil.nonNullState(StringConcatOperation.INSTANCE.evaluate(name, OclbugTables.STR__32_m_32));
		        final /*@Nullable*/ /*@Thrown*/ String key_2 = this.getKey();
		        final /*@NonNull*/ /*@Thrown*/ String concat_0 = DomainUtil.nonNullState(StringConcatOperation.INSTANCE.evaluate(concat, key_2));
		        symbol_4 = concat_0;
		    }
		    symbol_5 = symbol_4;
		}
		return symbol_5;
	}


It seems that 'this.getElement()' return null for which I tried to guard using the oclIsUndefined() clauses.

Might be my understanding of OCL or is this a bug in the generated code?

Greetings,
Wilbert.
  • Attachment: oclbug.zip
    (Size: 152.29KB, Downloaded 183 times)
Re: Possible bug in generated code [message #1697085 is a reply to message #1697076] Mon, 01 June 2015 13:20 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

The code is correct (although there is scope for future optimization):

final /*@NonNull*/ /*@Thrown*/ NamedElement element = this.getElement();

is the clue. /*@NonNull*/ indicates that the element cannot be null, so
the code omits the redundant null handling.

The model is

property element : NamedElement[1]
{
key name;
}

[1] prohibits a null. You must use [?] if a null value is well-formed at
any time that OCL may inspect it.

----

element.name.concat(' - ').concat(key)

You have been able to write

element.name + ' - ' + key

for a few years.

----

attribute id : String[?] { derived readonly transient volatile id }
{
derivation:
if element.oclIsUndefined()
then
if key.oclIsUndefined() then 'undefined' else key endif
else
if key.oclIsUndefined() then element.name else
element.name.concat(' - ').concat(key) endif
endif;
}

You should use an "initial" value rather than a "derivation" constraint.
The relative semantics of these has taken a long time to sort out and
has yet to be implemented. In due course the "derivation" return ill be
a Boolean success/failure indicator.

Regards

Ed Willink

On 01/06/2015 13:42, Wilbert Alberts wrote:
> Hi,
>
> I created an ecore model with a derived attribute specified in OCL. I decided to generate the java implementation of the OCL derivation. When using the derived attribute as label in the default generated tree editor, a NPE occurred.
>
> I suspect that the generated code is not correct; but I might be wrong. I added the eclipse projects (including generated code) as attachment.
>
> The oclbug.ecore describes a Documentation concept with a derived 'id' attribute. This attribute tries to construct a string based on the 'element' that is being document and a 'key'. The id is computed according to:
>
> if element.oclIsUndefined()
> then
> if key.oclIsUndefined() then 'undefined' else key endif
> else
> if key.oclIsUndefined() then element.name else element.name.concat(' - ').concat(key) endif
> endif;
>
> So I tried to guard against any undefined values of 'element' and/or 'key'. However when I try to create a Documentation instance (for which the 'element' has not been set) the NPE is thrown because the value of 'element' equals null. The generated code of the getId looks like (I highlight the line where the exception in thrown):
> public String getId() {
> /**
> *
> * if element.oclIsUndefined()
> * then if key.oclIsUndefined() then 'undefined' else key endif
> * else
> * if key.oclIsUndefined()
> * then element.name
> * else element.name.concat(' - ').concat(key)
> * endif
> * endif
> */
> /*@Nullable*/ /*@Caught*/ Object CAUGHT_key_1;
> try {
> final /*@Nullable*/ /*@Thrown*/ String key_1 = this.getKey();
> CAUGHT_key_1 = key_1;
> }
> catch (Exception e) {
> CAUGHT_key_1 = ValuesUtil.createInvalidValue(e);
> }
> final /*@NonInvalid*/ boolean symbol_3 = (CAUGHT_key_1 == null) || (CAUGHT_key_1 instanceof InvalidValueException);
> /*@NonNull*/ /*@Caught*/ Object CAUGHT_element;
> try {
> final /*@NonNull*/ /*@Thrown*/ NamedElement element = this.getElement();
> CAUGHT_element = element;
> }
> catch (Exception e) {
> CAUGHT_element = ValuesUtil.createInvalidValue(e);
> }
> final /*@NonInvalid*/ boolean symbol_0 = CAUGHT_element instanceof InvalidValueException;
> /*@Nullable*/ /*@Thrown*/ String symbol_5;
> if (symbol_0) {
> /*@Nullable*/ /*@Thrown*/ String symbol_2;
> if (symbol_3) {
> symbol_2 = OclbugTables.STR_undefined;
> }
> else {
> final /*@Nullable*/ /*@Thrown*/ String key_0 = this.getKey();
> symbol_2 = key_0;
> }
> symbol_5 = symbol_2;
> }
> else {
> final /*@NonNull*/ /*@Thrown*/ NamedElement element_0 = this.getElement();
> // Exception in next line ////////////////////////////////////////////////////////////////////
> final /*@Nullable*/ /*@Thrown*/ String name = element_0.getName();
> //////////////////////////////////////////////////////////////////////////////////////////////////
> /*@Nullable*/ /*@Thrown*/ String symbol_4;
> if (symbol_3) {
> symbol_4 = name;
> }
> else {
> final /*@NonNull*/ /*@Thrown*/ String concat = DomainUtil.nonNullState(StringConcatOperation.INSTANCE.evaluate(name, OclbugTables.STR__32_m_32));
> final /*@Nullable*/ /*@Thrown*/ String key_2 = this.getKey();
> final /*@NonNull*/ /*@Thrown*/ String concat_0 = DomainUtil.nonNullState(StringConcatOperation.INSTANCE.evaluate(concat, key_2));
> symbol_4 = concat_0;
> }
> symbol_5 = symbol_4;
> }
> return symbol_5;
> }
>
>
> It seems that 'this.getElement()' return null for which I tried to guard using the oclIsUndefined() clauses.
>
> Might be my understanding of OCL or is this a bug in the generated code?
>
> Greetings,
> Wilbert.
Re: Possible bug in generated code [message #1697166 is a reply to message #1697085] Tue, 02 June 2015 07:14 Go to previous messageGo to next message
Wilbert Alberts is currently offline Wilbert AlbertsFriend
Messages: 209
Registered: June 2010
Senior Member
Hi Ed,

You answer is clear. Indeed, making the 'element' optional solves the case.

Oh, and thanks for the .concat remark. I used the construct already for a long time in Acceleo but never thought of using it in the ecore ocl editor too. I thought it was an Acceleo extension.

I think that I don't get the reason about using 'initial' vs 'derived'. If I make it 'initial', then what happens if I change the value of 'element'. Will the value of 'id' be updated?

Is the (actual) semantics of them somewhere described? (I do own the EMF book but that might not be that accurate (anymore)).

Greetings and thanks,
Wilbert.
Re: Possible bug in generated code [message #1697197 is a reply to message #1697166] Tue, 02 June 2015 11:29 Go to previous message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7655
Registered: July 2009
Senior Member
Hi

Comment inline.

On 02/06/2015 08:14, Wilbert Alberts wrote:
> Oh, and thanks for the .concat remark. I used the construct already
> for a long time in Acceleo but never thought of using it in the ecore
> ocl editor too. I thought it was an Acceleo extension.
It was also a QVTo extension and such an obvious one that it got
promoted in, IIRC, OCL 2.3.
>
> I think that I don't get the reason about using 'initial' vs
> 'derived'. If I make it 'initial', then what happens if I change the
> value of 'element'. Will the value of 'id' be updated?
>
> Is the (actual) semantics of them somewhere described? (I do own the
> EMF book but that might not be that accurate (anymore)).
This is nothing to do with EMF, so don't look for guidance there.

In the Eclipse OCL code there was for a long time the problem; what is
the difference between initial and derived and if both are specified
which is used when? In the absence of clarity either could be used
interchangeably and if you specify both differently read the code to
discover what happens.

The OCL specification clause on OCL within UML is very weak, but it does
consistently refer to initial value expressions and derived value
constraints. Therefore an initial value expression is a query that
computes an initial value for readonly properties, or a prevailing
(derived) value for not-readonly properties. A derived value constraint,
is just another class invariant that must always be satisfied. It
differs from a class invariant solely through a relationship to a
Property; diagnostics can therefore refer more precisely to an
unsatisfactory Property rather than an unsatisfactory Class.

The above is my resolution of the vagueness. It is not yet accurately
reflected in the Pivot OCL code. There are at least a couple of related
outstanding bugs. When I tried to change your example to "initial", a
couple of GenModel synchronization issues distracted me.

Regards

Ed Willink
Previous Topic:Specification of operation bodies in 'plain Java' + OCL-based constraints
Next Topic:Unresolved namespace with generic
Goto Forum:
  


Current Time: Thu Apr 25 02:20:03 GMT 2024

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

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

Back to the top