Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Violation of EOpposites of cross references
Violation of EOpposites of cross references [message #548868] Fri, 23 July 2010 10:33 Go to next message
Christian Schneider is currently offline Christian SchneiderFriend
Messages: 23
Registered: July 2009
Junior Member
Hi all,

I've had a nasty problem since we introduced a cross reference with EOpposite relation in our domain model.

We have 'States' and 'Transitions' whereas a state has 'outgoing transitions' (containment, many) and a transition knows its 'target state' (EReference, non-containment).

Additionally, both references have an EOpposite reference:
the state knows 'incoming transitions' (many) and the transitions its 'source state' (which is more or less its eContainer).

Formally:

for the state:
initEReference(getState_OutgoingTransitions(), this.getTransition(), this.getTransition_SourceState(), "outgoingTransitions", null, 0, -1, State.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);

initEReference(getState_IncomingTransitions(), this.getTransition(), this.getTransition_TargetState(), "incomingTransitions", null, 0, -1, State.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);


for the transition:
initEReference(getTransition_TargetState(), this.getState(), this.getState_IncomingTransitions(), "targetState", null, 1, 1, Transition.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);

initEReference(getTransition_SourceState(), this.getState(), this.getState_OutgoingTransitions(), "sourceState", null, 1, 1, Transition.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);


The issue seems to be located in the following generated implementation method:

public State getTargetState() {
if (targetState != null && targetState.eIsProxy()) {
InternalEObject oldTargetState = (InternalEObject)targetState;
targetState = (State)eResolveProxy(oldTargetState);
if (targetState != oldTargetState) {
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.RESOLVE, SyncchartsPackage.TRANSITION__TARGET_STATE, oldTargetState, targetState));
}
}
return targetState;
}


Imagine the targetState reference is realized by a proxy instead of a full state.
Resolving the proxy via calling the method above will setup the targetState reference only and, hence, the EOpposite property is violated.


Any remarks on that bug?

Best,
Christian
Re: Violation of EOpposites of cross references [message #548940 is a reply to message #548868] Fri, 23 July 2010 13:41 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
Christian,

Comments below.


Christian Schneider wrote:
> Hi all,
>
> I've had a nasty problem since we introduced a cross reference with EOpposite relation in our domain model.
>
> We have 'States' and 'Transitions' whereas a state has 'outgoing transitions' (containment, many) and a transition knows its 'target state' (EReference, non-containment).
>
> Additionally, both references have an EOpposite reference:
> the state knows 'incoming transitions' (many) and the transitions its 'source state' (which is more or less its eContainer).
>
> Formally:
>
> for the state:
> initEReference(getState_OutgoingTransitions(), this.getTransition(), this.getTransition_SourceState(), "outgoingTransitions", null, 0, -1, State.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
>
> initEReference(getState_IncomingTransitions(), this.getTransition(), this.getTransition_TargetState(), "incomingTransitions", null, 0, -1, State.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
>
>
> for the transition:
> initEReference(getTransition_TargetState(), this.getState(), this.getState_IncomingTransitions(), "targetState", null, 1, 1, Transition.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
>
> initEReference(getTransition_SourceState(), this.getState(), this.getState_OutgoingTransitions(), "sourceState", null, 1, 1, Transition.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, !IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
>
>
> The issue seems to be located in the following generated implementation method:
>
> public State getTargetState() {
> if (targetState != null && targetState.eIsProxy()) {
> InternalEObject oldTargetState = (InternalEObject)targetState;
> targetState = (State)eResolveProxy(oldTargetState);
> if (targetState != oldTargetState) {
> if (eNotificationRequired())
> eNotify(new ENotificationImpl(this, Notification.RESOLVE, SyncchartsPackage.TRANSITION__TARGET_STATE, oldTargetState, targetState));
> }
> }
> return targetState;
> }
>
>
> Imagine the targetState reference is realized by a proxy instead of a full state.
> Resolving the proxy via calling the method above will setup the targetState reference only and, hence, the EOpposite property is violated.
>
I don't see how the hence follows. Could you elaborate? Note that in
the case of proxies both ends of the relationship must serialize and
hold a proxies, so there should be no problem with resolving the ends
separately. If you don't serialize them in separate documents, you can
make the relationship non-proxy resolving and you can then make one of
the ends transient (the single valued end if you want to preserve order
of the many side).
>
> Any remarks on that bug?
>
Given there must be proxies on both ends, there should be no bug.
> Best,
> Christian
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Violation of EOpposites of cross references [message #549281 is a reply to message #548940] Mon, 26 July 2010 11:16 Go to previous messageGo to next message
Christian Schneider is currently offline Christian SchneiderFriend
Messages: 23
Registered: July 2009
Junior Member
Ed,

> Given there must be proxies on both ends, there should be no bug.

This statement is the key to the actual root of the issue.

The sketched scenario arises while instantiating models with Xtext.
The framework builds up the model skeleton first (i.e. the elements and
their containment relations) and, if cross references within the model
occur, "link" them second.

However, linking means creating proxies aliasing the really addressed
elements. This is realized by a customized proxyURI that is stitched
together comprising information of the abstract parse tree - the
actually addressed EObject is not known yet and therefore the eOpposite
proxy can't be installed.

As usual, resolving a reference (here by means of custom scope
providers) occurs when the referenced object is called. Hence, the
earliest point in time the location/element to install the eOpposite on
is after 'getting' the proxied element once!

Oh dear!...

Looks like I have to customize the linking process to fix this.

Best,
Christian


On 7/23/10 3:41 PM, Ed Merks wrote:
> Christian,
>
> Comments below.
>
>
> Christian Schneider wrote:
>> Hi all,
>>
>> I've had a nasty problem since we introduced a cross reference with
>> EOpposite relation in our domain model.
>>
>> We have 'States' and 'Transitions' whereas a state has 'outgoing
>> transitions' (containment, many) and a transition knows its 'target
>> state' (EReference, non-containment).
>>
>> Additionally, both references have an EOpposite reference:
>> the state knows 'incoming transitions' (many) and the transitions its
>> 'source state' (which is more or less its eContainer).
>>
>> Formally:
>>
>> for the state:
>> initEReference(getState_OutgoingTransitions(), this.getTransition(),
>> this.getTransition_SourceState(), "outgoingTransitions", null, 0, -1,
>> State.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE,
>> !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
>>
>> initEReference(getState_IncomingTransitions(), this.getTransition(),
>> this.getTransition_TargetState(), "incomingTransitions", null, 0, -1,
>> State.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE,
>> !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE,
>> !IS_DERIVED, IS_ORDERED);
>>
>>
>> for the transition:
>> initEReference(getTransition_TargetState(), this.getState(),
>> this.getState_IncomingTransitions(), "targetState", null, 1, 1,
>> Transition.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE,
>> !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE,
>> !IS_DERIVED, IS_ORDERED);
>>
>> initEReference(getTransition_SourceState(), this.getState(),
>> this.getState_OutgoingTransitions(), "sourceState", null, 1, 1,
>> Transition.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE,
>> !IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE,
>> !IS_DERIVED, IS_ORDERED);
>>
>>
>> The issue seems to be located in the following generated
>> implementation method:
>>
>> public State getTargetState() {
>> if (targetState != null && targetState.eIsProxy()) {
>> InternalEObject oldTargetState = (InternalEObject)targetState;
>> targetState = (State)eResolveProxy(oldTargetState);
>> if (targetState != oldTargetState) {
>> if (eNotificationRequired())
>> eNotify(new ENotificationImpl(this,
>> Notification.RESOLVE, SyncchartsPackage.TRANSITION__TARGET_STATE,
>> oldTargetState, targetState));
>> }
>> }
>> return targetState;
>> }
>>
>>
>> Imagine the targetState reference is realized by a proxy instead of a
>> full state.
>> Resolving the proxy via calling the method above will setup the
>> targetState reference only and, hence, the EOpposite property is
>> violated.
>>
> I don't see how the hence follows. Could you elaborate? Note that in
> the case of proxies both ends of the relationship must serialize and
> hold a proxies, so there should be no problem with resolving the ends
> separately. If you don't serialize them in separate documents, you can
> make the relationship non-proxy resolving and you can then make one of
> the ends transient (the single valued end if you want to preserve order
> of the many side).
>>
>> Any remarks on that bug?
>>
> Given there must be proxies on both ends, there should be no bug.
>> Best,
>> Christian
>>
Re: Violation of EOpposites of cross references [message #549322 is a reply to message #549281] Mon, 26 July 2010 13:14 Go to previous message
Ed Merks is currently offline Ed MerksFriend
Messages: 33140
Registered: July 2009
Senior Member
This is a multi-part message in MIME format.
--------------010406080008040901030002
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit

Christian,

Comments below.

Christian Schneider wrote:
> Ed,
>
>
>> Given there must be proxies on both ends, there should be no bug.
>>
>
> This statement is the key to the actual root of the issue.
>
I'm a good guesser...
> The sketched scenario arises while instantiating models with Xtext.
> The framework builds up the model skeleton first (i.e. the elements and
> their containment relations) and, if cross references within the model
> occur, "link" them second.
>
I saw a posting on their newsgroup about bidirectional references and it
was pointed out that you'd need syntax at both ends. I mentioned that
if the references weren't cross document one could get away with syntax
on just one end...
> However, linking means creating proxies aliasing the really addressed
> elements. This is realized by a customized proxyURI that is stitched
> together comprising information of the abstract parse tree - the
> actually addressed EObject is not known yet and therefore the eOpposite
> proxy can't be installed.
>
Indeed. And if you start with the opposite, it will never know that it
needs a reference until the unknown and I supposed unknowable other end
reveals its presence.
> As usual, resolving a reference (here by means of custom scope
> providers) occurs when the referenced object is called. Hence, the
> earliest point in time the location/element to install the eOpposite on
> is after 'getting' the proxied element once!
>
Yes. We've avoided such behavior in the core because rather than
looking like a proxy resolve notification, such a change (a reference
that's not populated at all suddenly becoming populated) looks like an
actual modification of the instance.
> Oh dear!...
>
> Looks like I have to customize the linking process to fix this.
>
If you start at the end for which there is nothing serialized, will you
always know all the other ends that need to be processed in order to
fully populate all the opposites of the syntaxless starting point?
> Best,
> Christian
>
>
> On 7/23/10 3:41 PM, Ed Merks wrote:
>
>> Christian,
>>
>> Comments below.
>>
>>
>> Christian Schneider wrote:
>>
>>> Hi all,
>>>
>>> I've had a nasty problem since we introduced a cross reference with
>>> EOpposite relation in our domain model.
>>>
>>> We have 'States' and 'Transitions' whereas a state has 'outgoing
>>> transitions' (containment, many) and a transition knows its 'target
>>> state' (EReference, non-containment).
>>>
>>> Additionally, both references have an EOpposite reference:
>>> the state knows 'incoming transitions' (many) and the transitions its
>>> 'source state' (which is more or less its eContainer).
>>>
>>> Formally:
>>>
>>> for the state:
>>> initEReference(getState_OutgoingTransitions(), this.getTransition(),
>>> this.getTransition_SourceState(), "outgoingTransitions", null, 0, -1,
>>> State.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE,
>>> !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);
>>>
>>> initEReference(getState_IncomingTransitions(), this.getTransition(),
>>> this.getTransition_TargetState(), "incomingTransitions", null, 0, -1,
>>> State.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE,
>>> !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE,
>>> !IS_DERIVED, IS_ORDERED);
>>>
>>>
>>> for the transition:
>>> initEReference(getTransition_TargetState(), this.getState(),
>>> this.getState_IncomingTransitions(), "targetState", null, 1, 1,
>>> Transition.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE,
>>> !IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE,
>>> !IS_DERIVED, IS_ORDERED);
>>>
>>> initEReference(getTransition_SourceState(), this.getState(),
>>> this.getState_OutgoingTransitions(), "sourceState", null, 1, 1,
>>> Transition.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE,
>>> !IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE,
>>> !IS_DERIVED, IS_ORDERED);
>>>
>>>
>>> The issue seems to be located in the following generated
>>> implementation method:
>>>
>>> public State getTargetState() {
>>> if (targetState != null && targetState.eIsProxy()) {
>>> InternalEObject oldTargetState = (InternalEObject)targetState;
>>> targetState = (State)eResolveProxy(oldTargetState);
>>> if (targetState != oldTargetState) {
>>> if (eNotificationRequired())
>>> eNotify(new ENotificationImpl(this,
>>> Notification.RESOLVE, SyncchartsPackage.TRANSITION__TARGET_STATE,
>>> oldTargetState, targetState));
>>> }
>>> }
>>> return targetState;
>>> }
>>>
>>>
>>> Imagine the targetState reference is realized by a proxy instead of a
>>> full state.
>>> Resolving the proxy via calling the method above will setup the
>>> targetState reference only and, hence, the EOpposite property is
>>> violated.
>>>
>>>
>> I don't see how the hence follows. Could you elaborate? Note that in
>> the case of proxies both ends of the relationship must serialize and
>> hold a proxies, so there should be no problem with resolving the ends
>> separately. If you don't serialize them in separate documents, you can
>> make the relationship non-proxy resolving and you can then make one of
>> the ends transient (the single valued end if you want to preserve order
>> of the many side).
>>
>>> Any remarks on that bug?
>>>
>>>
>> Given there must be proxies on both ends, there should be no bug.
>>
>>> Best,
>>> Christian
>>>
>>>
>
>

--------------010406080008040901030002
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
Christian,<br>
<br>
Comments below.<br>
<br>
Christian Schneider wrote:
<blockquote cite="mid:4C4D6E7B.20702@informatik.uni-kiel.de" type="cite">
<pre wrap="">Ed,

</pre>
<blockquote type="cite">
<pre wrap="">Given there must be proxies on both ends, there should be no bug.
</pre>
</blockquote>
<pre wrap=""><!---->
This statement is the key to the actual root of the issue.
</pre>
</blockquote>
I'm a good guesser...<br>
<blockquote cite="mid:4C4D6E7B.20702@informatik.uni-kiel.de" type="cite">
<pre wrap="">
The sketched scenario arises while instantiating models with Xtext.
The framework builds up the model skeleton first (i.e. the elements and
their containment relations) and, if cross references within the model
occur, "link" them second.
</pre>
</blockquote>
I saw a posting on their newsgroup about bidirectional references and
it was pointed out that you'd need syntax at both ends.&nbsp; I mentioned
that if the references weren't cross document one could get away with
syntax on just one end...<br>
<blockquote cite="mid:4C4D6E7B.20702@informatik.uni-kiel.de" type="cite">
<pre wrap="">
However, linking means creating proxies aliasing the really addressed
elements. This is realized by a customized proxyURI that is stitched
together comprising information of the abstract parse tree - the
actually addressed EObject is not known yet and therefore the eOpposite
proxy can't be installed.
</pre>
</blockquote>
Indeed.&nbsp; And if you start with the opposite, it will never know that it
needs a reference until the unknown and I supposed unknowable other end
reveals its presence.<br>
<blockquote cite="mid:4C4D6E7B.20702@informatik.uni-kiel.de" type="cite">
<pre wrap="">
As usual, resolving a reference (here by means of custom scope
providers) occurs when the referenced object is called. Hence, the
earliest point in time the location/element to install the eOpposite on
is after 'getting' the proxied element once!
</pre>
</blockquote>
Yes.&nbsp; We've avoided such behavior in the core because rather than
looking like a proxy resolve notification, such a change (a reference
that's not populated at all suddenly becoming populated) looks like an
actual modification of the instance.<br>
<blockquote cite="mid:4C4D6E7B.20702@informatik.uni-kiel.de" type="cite">
<pre wrap="">
Oh dear!...

Looks like I have to customize the linking process to fix this.
</pre>
</blockquote>
If you start at the end for which there is nothing serialized, will you
always know all the other ends that need to be processed in order to
fully populate all the opposites of the syntaxless starting point?<br>
<blockquote cite="mid:4C4D6E7B.20702@informatik.uni-kiel.de" type="cite">
<pre wrap="">
Best,
Christian


On 7/23/10 3:41 PM, Ed Merks wrote:
</pre>
<blockquote type="cite">
<pre wrap="">Christian,

Comments below.


Christian Schneider wrote:
</pre>
<blockquote type="cite">
<pre wrap="">Hi all,

I've had a nasty problem since we introduced a cross reference with
EOpposite relation in our domain model.

We have 'States' and 'Transitions' whereas a state has 'outgoing
transitions' (containment, many) and a transition knows its 'target
state' (EReference, non-containment).

Additionally, both references have an EOpposite reference:
the state knows 'incoming transitions' (many) and the transitions its
'source state' (which is more or less its eContainer).

Formally:

for the state:
initEReference(getState_OutgoingTransitions(), this.getTransition(),
this.getTransition_SourceState(), "outgoingTransitions", null, 0, -1,
State.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE, IS_COMPOSITE,
!IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE, !IS_DERIVED, IS_ORDERED);

initEReference(getState_IncomingTransitions(), this.getTransition(),
this.getTransition_TargetState(), "incomingTransitions", null, 0, -1,
State.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE,
!IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE,
!IS_DERIVED, IS_ORDERED);


for the transition:
initEReference(getTransition_TargetState(), this.getState(),
this.getState_IncomingTransitions(), "targetState", null, 1, 1,
Transition.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE,
!IS_COMPOSITE, IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE,
!IS_DERIVED, IS_ORDERED);

initEReference(getTransition_SourceState(), this.getState(),
this.getState_OutgoingTransitions(), "sourceState", null, 1, 1,
Transition.class, !IS_TRANSIENT, !IS_VOLATILE, IS_CHANGEABLE,
!IS_COMPOSITE, !IS_RESOLVE_PROXIES, !IS_UNSETTABLE, IS_UNIQUE,
!IS_DERIVED, IS_ORDERED);


The issue seems to be located in the following generated
implementation method:

public State getTargetState() {
if (targetState != null &amp;&amp; targetState.eIsProxy()) {
InternalEObject oldTargetState = (InternalEObject)targetState;
targetState = (State)eResolveProxy(oldTargetState);
if (targetState != oldTargetState) {
if (eNotificationRequired())
eNotify(new ENotificationImpl(this,
Notification.RESOLVE, SyncchartsPackage.TRANSITION__TARGET_STATE,
oldTargetState, targetState));
}
}
return targetState;
}


Imagine the targetState reference is realized by a proxy instead of a
full state.
Resolving the proxy via calling the method above will setup the
targetState reference only and, hence, the EOpposite property is
violated.

</pre>
</blockquote>
<pre wrap="">I don't see how the hence follows. Could you elaborate? Note that in
the case of proxies both ends of the relationship must serialize and
hold a proxies, so there should be no problem with resolving the ends
separately. If you don't serialize them in separate documents, you can
make the relationship non-proxy resolving and you can then make one of
the ends transient (the single valued end if you want to preserve order
of the many side).
</pre>
<blockquote type="cite">
<pre wrap="">Any remarks on that bug?

</pre>
</blockquote>
<pre wrap="">Given there must be proxies on both ends, there should be no bug.
</pre>
<blockquote type="cite">
<pre wrap="">Best,
Christian

</pre>
</blockquote>
</blockquote>
<pre wrap=""><!---->
</pre>
</blockquote>
</body>
</html>

--------------010406080008040901030002--


Ed Merks
Professional Support: https://www.macromodeling.com/
Previous Topic:[Newbie] Filtering selection choices on references?
Next Topic:[CDO] GASTRO Sample Application Code
Goto Forum:
  


Current Time: Thu Apr 25 07:00:16 GMT 2024

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

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

Back to the top