Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Strategies for handling dangling references?
Strategies for handling dangling references? [message #875390] Tue, 22 May 2012 16:44 Go to next message
Eric Rizzo is currently offline Eric RizzoFriend
Messages: 3070
Registered: July 2009
Senior Member
So I have an ecore model and some custom editors to edit the instances. A dilemma we've run into relates to dangling references, specifically references to contained objects that are then removed from their container. For example, if I have a model like this:

EmailAddress
Person (contains an EmailAddress)
Message (references an EmailAddress)

Assume I have a Person, joe, and a Message that refers to joe's EmailAddress. If I edit joe and delete his EmailAddress, the Message will have a dangling reference. Which means that the Message can no longer be edited and saved - the save will fail because it can't resolve the reference to joe's EmailAddress.

So we're looking for strategies to solve this in a real-world application. There are lots of reasons to want to mark an error on the Message but still allow the user to load, edit, and save it. I'm curious about how other people have solved this problem in a user-friendly way.

One idea we've been tossing around is to re-parent deleted contained objects into a "tombstone" container, so that the references to them are still valid. I can see a couple of potential problems with that approach, such as what URI does the "tombstone" container use so that there is enough information about the original container to be useful in error markers, quick-fix, etc. Following the above example model, this idea would mean that when joe's email address is deleted, it would be placed in a "dummy" Person (joe_tombstone) so that the Message's reference is still valid as far as EMF is concerned. We'd have to build some custom mechanism to find and handle those during our build, too.
Any thoughts on that idea (such as, "warning: there be dragons")? Or any other ideas?

Thanks,
Eric
Re: Strategies for handling dangling references? [message #875427 is a reply to message #875390] Tue, 22 May 2012 18:29 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33113
Registered: July 2009
Senior Member
Eric,

Comments below.

On 22/05/2012 6:44 PM, Eric Rizzo wrote:
> So I have an ecore model and some custom editors to edit the
> instances. A dilemma we've run into relates to dangling references,
> specifically references to contained objects that are then removed
> from their container. For example, if I have a model like this:
>
> EmailAddress
> Person (contains an EmailAddress)
> Message (references an EmailAddress)
>
> Assume I have a Person, joe, and a Message that refers to joe's
> EmailAddress. If I edit joe and delete his EmailAddress, the Message
> will have a dangling reference. Which means that the Message can no
> longer be edited and saved - the save will fail because it can't
> resolve the reference to joe's EmailAddress.
There are these options:

String OPTION_PROCESS_DANGLING_HREF = "PROCESS_DANGLING_HREF";
String OPTION_PROCESS_DANGLING_HREF_THROW = "THROW";
String OPTION_PROCESS_DANGLING_HREF_DISCARD = "DISCARD";
String OPTION_PROCESS_DANGLING_HREF_RECORD = "RECORD";
>
> So we're looking for strategies to solve this in a real-world
> application. There are lots of reasons to want to mark an error on the
> Message but still allow the user to load, edit, and save it. I'm
> curious about how other people have solved this problem in a
> user-friendly way.
It's pretty easy to find all the dangling reference and remove them.
EcoreUtil.UnresolvedProxyCrossReferencer is handy...
>
> One idea we've been tossing around is to re-parent deleted contained
> objects into a "tombstone" container, so that the references to them
> are still valid. I can see a couple of potential problems with that
> approach, such as what URI does the "tombstone" container use so that
> there is enough information about the original container to be useful
> in error markers, quick-fix, etc.
Is the problem more one of saving (the options are good for that) or of
loading (there will be broken proxies)?
> Following the above example model, this idea would mean that when
> joe's email address is deleted, it would be placed in a "dummy" Person
> (joe_tombstone) so that the Message's reference is still valid as far
> as EMF is concerned. We'd have to build some custom mechanism to find
> and handle those during our build, too.
How much information is in the broken proxy? Clever use of fragment
paths that include names of the things along the path could be helpful...
> Any thoughts on that idea (such as, "warning: there be dragons")? Or
> any other ideas?
>
> Thanks,
> Eric
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Strategies for handling dangling references? [message #876510 is a reply to message #875427] Thu, 24 May 2012 18:41 Go to previous messageGo to next message
Eric Rizzo is currently offline Eric RizzoFriend
Messages: 3070
Registered: July 2009
Senior Member
Ed Merks wrote on Tue, 22 May 2012 14:29
Eric,
Comments below.

On 22/05/2012 6:44 PM, Eric Rizzo wrote:
> So I have an ecore model and some custom editors to edit the
> instances. A dilemma we've run into relates to dangling references,
> specifically references to contained objects that are then removed
> from their container. For example, if I have a model like this:
>
> EmailAddress
> Person (contains an EmailAddress)
> Message (references an EmailAddress)
>
> Assume I have a Person, joe, and a Message that refers to joe's
> EmailAddress. If I edit joe and delete his EmailAddress, the Message
> will have a dangling reference. Which means that the Message can no
> longer be edited and saved - the save will fail because it can't
> resolve the reference to joe's EmailAddress.

There are these options:

String OPTION_PROCESS_DANGLING_HREF = "PROCESS_DANGLING_HREF";
String OPTION_PROCESS_DANGLING_HREF_THROW = "THROW";
String OPTION_PROCESS_DANGLING_HREF_DISCARD = "DISCARD";
String OPTION_PROCESS_DANGLING_HREF_RECORD = "RECORD";

In my tests, using the DISCARD or RECORD options result in the save succeeding but the reference being set to null. That's not desirable in our application, because it amounts to changing something the user did not expect.

Quote:

> So we're looking for strategies to solve this in a real-world
> application. There are lots of reasons to want to mark an error on the
> Message but still allow the user to load, edit, and save it. I'm
> curious about how other people have solved this problem in a
> user-friendly way.

It's pretty easy to find all the dangling reference and remove them.
EcoreUtil.UnresolvedProxyCrossReferencer is handy...

We can't just remove them, for various reasons. It's just not a user-friendly thing to do (at least in our application). The user needs to be able to load, edit, and save a model that has one of these dangling references, without losing the reference entirely when he saves.

Quote:

> One idea we've been tossing around is to re-parent deleted contained
> objects into a "tombstone" container, so that the references to them
> are still valid. I can see a couple of potential problems with that
> approach, such as what URI does the "tombstone" container use so that
> there is enough information about the original container to be useful
> in error markers, quick-fix, etc.

Is the problem more one of saving (the options are good for that) or of
loading (there will be broken proxies)?

The problem, for now at least, is saving. We want the user to be able to save models that have a reference to a an orphaned fragment, but not lose the information about that reference (essentially, its URI). That's because we want users to be able to edit other parts of the model while the orphaned reference is present.

Quote:

> Following the above example model, this idea would mean that when
> joe's email address is deleted, it would be placed in a "dummy" Person
> (joe_tombstone) so that the Message's reference is still valid as far
> as EMF is concerned. We'd have to build some custom mechanism to find
> and handle those during our build, too.
How much information is in the broken proxy? Clever use of fragment
paths that include names of the things along the path could be helpful...
>

I'm not understanding you. The reference URI does have useful information, including the original container(s) of the fragment, true.
What do you think of the "tombstone" idea? Do you see any major hurdles or pitfalls down that path?
Better yet, do you have any other recommendations for how to address our basic need (re-stated above, hopefully more clearly)?

Thanks,
Eric
Re: Strategies for handling dangling references? [message #876538 is a reply to message #876510] Thu, 24 May 2012 20:04 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33113
Registered: July 2009
Senior Member
Eric,

Comments below.

On 24/05/2012 8:41 PM, Eric Rizzo wrote:
> Ed Merks wrote on Tue, 22 May 2012 14:29
>> Eric,
>> Comments below.
>>
>> On 22/05/2012 6:44 PM, Eric Rizzo wrote:
>> > So I have an ecore model and some custom editors to edit the >
>> instances. A dilemma we've run into relates to dangling references, >
>> specifically references to contained objects that are then removed >
>> from their container. For example, if I have a model like this:
>> >
>> > EmailAddress
>> > Person (contains an EmailAddress)
>> > Message (references an EmailAddress)
>> >
>> > Assume I have a Person, joe, and a Message that refers to joe's >
>> EmailAddress. If I edit joe and delete his EmailAddress, the Message
>> > will have a dangling reference. Which means that the Message can no
>> > longer be edited and saved - the save will fail because it can't >
>> resolve the reference to joe's EmailAddress.
>>
>> There are these options:
>>
>> String OPTION_PROCESS_DANGLING_HREF =
>> "PROCESS_DANGLING_HREF";
>> String OPTION_PROCESS_DANGLING_HREF_THROW = "THROW";
>> String OPTION_PROCESS_DANGLING_HREF_DISCARD = "DISCARD";
>> String OPTION_PROCESS_DANGLING_HREF_RECORD = "RECORD";
>
> In my tests, using the DISCARD or RECORD options result in the save
> succeeding but the reference being set to null. That's not desirable
> in our application, because it amounts to changing something the user
> did not expect.
>
> Quote:
>> > So we're looking for strategies to solve this in a real-world >
>> application. There are lots of reasons to want to mark an error on
>> the > Message but still allow the user to load, edit, and save it.
>> I'm > curious about how other people have solved this problem in a >
>> user-friendly way.
>>
>> It's pretty easy to find all the dangling reference and remove them.
>> EcoreUtil.UnresolvedProxyCrossReferencer is handy...
>
> We can't just remove them, for various reasons. It's just not a
> user-friendly thing to do (at least in our application). The user
> needs to be able to load, edit, and save a model that has one of these
> dangling references, without losing the reference entirely when he saves.
You could convert them into proxies, so they're saved with whatever
proxy URI you set. Upon loading, you'll have an unresolved proxy with
that URI again...
>
> Quote:
>> > One idea we've been tossing around is to re-parent deleted
>> contained > objects into a "tombstone" container, so that the
>> references to them > are still valid. I can see a couple of potential
>> problems with that > approach, such as what URI does the "tombstone"
>> container use so that > there is enough information about the
>> original container to be useful > in error markers, quick-fix, etc.
>> Is the problem more one of saving (the options are good for that) or
>> of loading (there will be broken proxies)?
>
> The problem, for now at least, is saving. We want the user to be able
> to save models that have a reference to a an orphaned fragment, but
> not lose the information about that reference (essentially, its URI).
It has no URI once it's removed from its container. Perhaps you set a
proxy URI to it while you remove it from the container...
> That's because we want users to be able to edit other parts of the
> model while the orphaned reference is present.
They'll fix it at some point?
>
> Quote:
>> > Following the above example model, this idea would mean that when >
>> joe's email address is deleted, it would be placed in a "dummy"
>> Person > (joe_tombstone) so that the Message's reference is still
>> valid as far > as EMF is concerned. We'd have to build some custom
>> mechanism to find > and handle those during our build, too.
>> How much information is in the broken proxy? Clever use of fragment
>> paths that include names of the things along the path could be
>> helpful...
>> >
>
> I'm not understanding you. The reference URI does have useful
> information, including the original container(s) of the fragment, true.
Once resolved, you only have the object, and once it's orphaned you have
no information for how it should be relocated or what it's URI should be
upon saving...
> What do you think of the "tombstone" idea?
It's okay, but not so different from setting a proxy URI and saving it
that way.
> Do you see any major hurdles or pitfalls down that path?
No, but do they ever get deleted or cleaned up.
> Better yet, do you have any other recommendations for how to address
> our basic need (re-stated above, hopefully more clearly)?
Setting a proxy URI would be okay. Not sure what it should be...
>
> Thanks,
> Eric
>


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Strategies for handling dangling references? [message #896014 is a reply to message #876538] Mon, 16 July 2012 22:38 Go to previous messageGo to next message
Eric Rizzo is currently offline Eric RizzoFriend
Messages: 3070
Registered: July 2009
Senior Member
Revisiting an old topic, now that we've implemented part of a solution. More below, at the end...

Ed Merks wrote on Thu, 24 May 2012 16:04
Eric,

Comments below.

On 24/05/2012 8:41 PM, Eric Rizzo wrote:
> Ed Merks wrote on Tue, 22 May 2012 14:29
>> Eric,
>> Comments below.
>>
>> On 22/05/2012 6:44 PM, Eric Rizzo wrote:
>> > So I have an ecore model and some custom editors to edit the >
>> instances. A dilemma we've run into relates to dangling references, >
>> specifically references to contained objects that are then removed >
>> from their container. For example, if I have a model like this:
>> >
>> > EmailAddress
>> > Person (contains an EmailAddress)
>> > Message (references an EmailAddress)
>> >
>> > Assume I have a Person, joe, and a Message that refers to joe's >
>> EmailAddress. If I edit joe and delete his EmailAddress, the Message
>> > will have a dangling reference. Which means that the Message can no
>> > longer be edited and saved - the save will fail because it can't >
>> resolve the reference to joe's EmailAddress.
>> > So we're looking for strategies to solve this in a real-world >
>> application. There are lots of reasons to want to mark an error on
>> the > Message but still allow the user to load, edit, and save it.
>> I'm > curious about how other people have solved this problem in a >
>> user-friendly way.
>>
>
> We can't just remove them, for various reasons. It's just not a
> user-friendly thing to do (at least in our application). The user
> needs to be able to load, edit, and save a model that has one of these
> dangling references, without losing the reference entirely when he saves.

You could convert them into proxies, so they're saved with whatever
proxy URI you set. Upon loading, you'll have an unresolved proxy with
that URI again...
>
> Quote:
> The problem, for now at least, is saving. We want the user to be able
> to save models that have a reference to a an orphaned fragment, but
> not lose the information about that reference (essentially, its URI).

It has no URI once it's removed from its container. Perhaps you set a
proxy URI to it while you remove it from the container...

> That's because we want users to be able to edit other parts of the
> model while the orphaned reference is present.

They'll fix it at some point?

Setting a proxy URI would be okay. Not sure what it should be...


The strategy we've taken is to find all external references and set a proxy URI on them. It seems to work, except for one important wrinkle. Our editors use the EMF Edit framework, so all model edits are happening via Commands. If the user removes the contained object (EmailAddress) in the editor, the references are found and proxy-fied. Unfortunately, that includes the original object that was removed. So if the user invokes Undo, the Command puts the original back into its container, but that instance is now a proxy. Worse part is, I can't seem to re-resolve it now. I've tried ECoreUtil.resolve() but it fails to find the object; it's already back in it's container but is still a proxy.

Any ideas how I can either
A) prevent the original instance from being proxified; I don't think this is possible because of instance caching the instance that is found when searching for external references is the same as the one that is removed from the container.
B) Re-resolve the proxy instance during or after Undo

Thanks again,
Eric
Re: Strategies for handling dangling references? [message #896054 is a reply to message #896014] Tue, 17 July 2012 05:40 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33113
Registered: July 2009
Senior Member
Eric,

Comments below.

On 17/07/2012 12:38 AM, Eric Rizzo wrote:
> Revisiting an old topic, now that we've implemented part of a
> solution. More below, at the end...
>
> Ed Merks wrote on Thu, 24 May 2012 16:04
>> Eric,
>>
>> Comments below.
>>
>> On 24/05/2012 8:41 PM, Eric Rizzo wrote:
>> > Ed Merks wrote on Tue, 22 May 2012 14:29
>> >> Eric,
>> >> Comments below.
>> >>
>> >> On 22/05/2012 6:44 PM, Eric Rizzo wrote:
>> >> > So I have an ecore model and some custom editors to edit the >
>> >> instances. A dilemma we've run into relates to dangling
>> references, > >> specifically references to contained objects that
>> are then removed > >> from their container. For example, if I have a
>> model like this:
>> >> >
>> >> > EmailAddress
>> >> > Person (contains an EmailAddress)
>> >> > Message (references an EmailAddress)
>> >> >
>> >> > Assume I have a Person, joe, and a Message that refers to joe's
>> > >> EmailAddress. If I edit joe and delete his EmailAddress, the
>> Message >> > will have a dangling reference. Which means that the
>> Message can no >> > longer be edited and saved - the save will fail
>> because it can't > >> resolve the reference to joe's EmailAddress.
>> >> > So we're looking for strategies to solve this in a real-world >
>> >> application. There are lots of reasons to want to mark an error on
>> >> the > Message but still allow the user to load, edit, and save it.
>> >> I'm > curious about how other people have solved this problem in a
>> > >> user-friendly way.
>> >>
>> >
>> > We can't just remove them, for various reasons. It's just not a >
>> user-friendly thing to do (at least in our application). The user >
>> needs to be able to load, edit, and save a model that has one of
>> these > dangling references, without losing the reference entirely
>> when he saves.
>>
>> You could convert them into proxies, so they're saved with whatever
>> proxy URI you set. Upon loading, you'll have an unresolved proxy
>> with that URI again...
>> >
>> > Quote:
>> > The problem, for now at least, is saving. We want the user to be
>> able > to save models that have a reference to a an orphaned
>> fragment, but > not lose the information about that reference
>> (essentially, its URI).
>> It has no URI once it's removed from its container. Perhaps you set
>> a proxy URI to it while you remove it from the container...
>>
>> > That's because we want users to be able to edit other parts of the
>> > model while the orphaned reference is present.
>>
>> They'll fix it at some point?
>>
>> Setting a proxy URI would be okay. Not sure what it should be...
>
>
> The strategy we've taken is to find all external references and set a
> proxy URI on them. It seems to work, except for one important wrinkle.
> Our editors use the EMF Edit framework, so all model edits are
> happening via Commands. If the user removes the contained object
> (EmailAddress) in the editor, the references are found and proxy-fied.
> Unfortunately, that includes the original object that was removed. So
> if the user invokes Undo, the Command puts the original back into its
> container, but that instance is now a proxy. Worse part is, I can't
> seem to re-resolve it now. I've tried ECoreUtil.resolve() but it fails
> to find the object; it's already back in it's container but is still a
> proxy.
It would just resolve to itself. The proxification should be done as a
command and of course that should implement undo to unproxify it.
>
> Any ideas how I can either
> A) prevent the original instance from being proxified; I don't think
> this is possible because of instance caching the instance that is
> found when searching for external references is the same as the one
> that is removed from the container.
No, I think you need to proxify it. Otherwise you need to swizzle all a
references, and of course then you'd have an even bigger undo problem.
> B) Re-resolve the proxy instance during or after Undo
I think only the proxy URI needs to be set back to null again...
>
> Thanks again,
> Eric


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Strategies for handling dangling references? [message #896531 is a reply to message #896054] Wed, 18 July 2012 17:28 Go to previous message
Eric Rizzo is currently offline Eric RizzoFriend
Messages: 3070
Registered: July 2009
Senior Member
Ed Merks wrote on Tue, 17 July 2012 01:40

Eric,

Comments below.

On 17/07/2012 12:38 AM, Eric Rizzo wrote:
> The strategy we've taken is to find all external references and set a
> proxy URI on them. It seems to work, except for one important wrinkle.
> Our editors use the EMF Edit framework, so all model edits are
> happening via Commands. If the user removes the contained object
> (EmailAddress) in the editor, the references are found and proxy-fied.
> Unfortunately, that includes the original object that was removed. So
> if the user invokes Undo, the Command puts the original back into its
> container, but that instance is now a proxy. Worse part is, I can't
> seem to re-resolve it now. I've tried ECoreUtil.resolve() but it fails
> to find the object; it's already back in it's container but is still a
> proxy.

It would just resolve to itself. The proxification should be done as a
command and of course that should implement undo to unproxify it.

Before, I wasn't including the proxification as part of the edit command (I was doing it manually after Command execution); now I've implemented a custom Command that can do it (and undo as well) and use a CompoundCommand to execute it after the RemoveCommand. Seems to work quite well.

Quote:

> Any ideas how I can either
> A) prevent the original instance from being proxified; I don't think
> this is possible because of instance caching the instance that is
> found when searching for external references is the same as the one
> that is removed from the container.

No, I think you need to proxify it. Otherwise you need to swizzle all a
references, and of course then you'd have an even bigger undo problem.

> B) Re-resolve the proxy instance during or after Undo

I think only the proxy URI needs to be set back to null again...

You're right, just setting the proxy URI back to null un-does the proxification nicely. I've only done smoke testing, but so far it appears to be a good solution.

Eric
Previous Topic:New child menu entry for EMap and custom dialog
Next Topic:[xcore] problem referencing UML classes?
Goto Forum:
  


Current Time: Fri Mar 29 13:18:57 GMT 2024

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

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

Back to the top