Given some EObject x that's a resolved proxy held by feature f of object
y, you can use EcoreUtil.create(x.eClass()), cast it to InternalEObject,
call setEProxyURI with EcoreUtil.getURI(x), and then use
EcoreUtil.replace(y, f, x, <that proxy object>).

The problem we are running into is that this approach doesn't work when the EReference's type is abstract. Instead EcoreUtil.create throws an IllegalArgumentException with the message "The class XXX is not a valid classifier".

The only workaround we have found so far is to remove the abstract flag from the EReference's EClass type. We'd prefer not to do that since the base class really is abstract, and if/when the proxy is resolved it will resolve to the proper subclass.

Is there another approach? On the surface I don't see why we can't have a proxy object of the abstract class's type that will resolve to a concerete class type. Since EReference attributes don't contain type information this doesn't seem to be a requirement in the serialization format either.

On 27/01/2013 10:34 PM, David Rees wrote:
> We are trying to create a proxy object for a cross-resource EReference
> where the other resource has not been loaded yet. So we can't just
> grab its EObject.
> I found this approach from Ed at
> http://www.eclipse.org/forums/index.php/mv/msg/205677/658272/#msg_658272:
> Ed Merks wrote on Mon, 07 March 2011 11:26
>> Given some EObject x that's a resolved proxy held by feature f of
>> object y, you can use EcoreUtil.create(x.eClass()), cast it to
>> InternalEObject, call setEProxyURI with EcoreUtil.getURI(x), and then
>> use EcoreUtil.replace(y, f, x, <that proxy object>).
>
>
> The problem we are running into is that this approach doesn't work
> when the EReference's type is abstract.
That post was asking about converting an existing object back to a
proxy, not about creating a proxy out of thin air...
> Instead EcoreUtil.create throws an IllegalArgumentException with the
> message "The class XXX is not a valid classifier".
>
> The only workaround we have found so far is to remove the abstract
> flag from the EReference's EClass type. We'd prefer not to do that
> since the base class really is abstract, and if/when the proxy is
> resolved it will resolve to the proper subclass.
>
> Is there another approach?
You need to determine a concrete subclass of the abstract class. That's
why in an XMI serialization there will always be an xsi/xmi type on such
a proxy reference...
> On the surface I don't see why we can't have a proxy object of the
> abstract class's type that will resolve to a concerete class type.
It's not that you can't have one. The problem is, just as an in Java,
if you have an abstract class X, you can do "new X()", and you can't
even do it reflectively.
> Since EReference attributes don't contain type information this
> doesn't seem to be a requirement in the serialization format either.
As I mentioned above, the serialization will always specify an xsi:type
in these cases because the actual object will be a concrete subclass and
creating a proxy requires that information.

Given you're trying to create a proxy for something instantiable, don't
you already know the non-abstract class of that something? Note that,
although it's quite odd, it's not necessary that the proxy will resolve
to an object that's a subclass of the proxy, so you could choose any
arbitrary concrete subclass for the proxy. But as I suggested with my
previous question, it seems odd that you'd know the proxy URI but not
know the type of the target for that URI...
> Thanks,
> dave
>
>
>]]>Ed Merks2013-01-28T06:54:53-00:00Re: Create proxy object for abstract reference typehttps://www.eclipse.org/forums/index.php/mv/msg/452171/1005751/#msg_1005751
Ed Merks wrote on Mon, 28 January 2013 01:54

David,

Comments below.

On 27/01/2013 10:34 PM, David Rees wrote:
> The problem we are running into is that this approach doesn't work
> when the EReference's type is abstract.
That post was asking about converting an existing object back to a
proxy, not about creating a proxy out of thin air...

Yes, I know. Just wanted to point out where we got the original idea for the approach.

Quote:

Given you're trying to create a proxy for something instantiable, don't
you already know the non-abstract class of that something?

No we don't, that file may not have been loaded/created yet. For example we are loading a bunch of existing XML files that may contain keys (with no type info) for elements in files we have not processed yet. Happily the fact that proxies do not have to be resolved allows us to handle this case.

Quote:

> Is there another approach?
You need to determine a concrete subclass of the abstract class. That's
why in an XMI serialization there will always be an xsi/xmi type on such
a proxy reference...

[quote]Note that, although it's quite odd, it's not necessary that the proxy will resolve
to an object that's a subclass of the proxy, so you could choose any
arbitrary concrete subclass for the proxy. But as I suggested with my
previous question, it seems odd that you'd know the proxy URI but not
know the type of the target for that URI...

Thanks, we were wondering about this approach. It will let us avoid modifying the metamodel, but I guess we will need to be more careful when working with proxies. Actually, we have already figured out we need to be careful anyway since it seems if a resolve fails the instance just returns nil for all its features rather than throwing an error.

Quote:

> On the surface I don't see why we can't have a proxy object of the
> abstract class's type that will resolve to a concerete class type.
It's not that you can't have one. The problem is, just as an in Java,
if you have an abstract class X, you can do "new )", and you can't
even do it reflectively.

Sorry, I'm missing the difference between "can't have one" and "can't create one". Are they not one and the same in this case or am I missing something?

At a theory level, we are not trying to instantiate the target instance, we are trying to instantiate its proxy which is practically possible in many other proxy frameworks. As you mentioned, even the EMF recognizes that its choice of proxy type is just a guess since it can change (and easily could since they are in different files).

Quote:

> Since EReference attributes don't contain type information this
> doesn't seem to be a requirement in the serialization format either.
As I mentioned above, the serialization will always specify an xsi:type
in these cases because the actual object will be a concrete subclass and
creating a proxy requires that information.

And if the root class isn't abstract then EMF doesn't generate the xsi:types, further underscoring that EMF doesn't need them for resolving - it just needs them to get around the limitation on instantiating the abstract class instances (even as proxies). Still, I can understand if there are assumptions in the implementation that don't expect an abstract instance to exist even as a proxy.

Thanks! It's very helpful to understand the underlying logic.

dave

]]>David Rees2013-01-28T14:52:52-00:00Re: Create proxy object for abstract reference typehttps://www.eclipse.org/forums/index.php/mv/msg/452171/1005758/#msg_1005758
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
</head>
<body text="#000000" bgcolor="#FFFFFF">
David,<br>
<br>
Comments below.<br>
<br>
<div class="moz-cite-prefix">On 28/01/2013 3:52 PM, David Rees
wrote:<br>
</div>
<blockquote cite="mid:ke63c5$jbu$1@xxxxxxxxe.org" type="cite">Ed
Merks wrote on Mon, 28 January 2013 01:54
<br>
<blockquote type="cite">David,
<br>
<br>
Comments below.
<br>
<br>
On 27/01/2013 10:34 PM, David Rees wrote:
<br>
&gt; The problem we are running into is that this approach
doesn't work &gt; when the EReference's type is abstract.
<br>
That post was asking about converting an existing object back to
a proxy, not about creating a proxy out of thin air...
<br>
</blockquote>
<br>
<br>
Yes, I know. Just wanted to point out where we got the original
idea for the approach.
<br>
<br>
<br>
Quote:
<br>
<blockquote type="cite">Given you're trying to create a proxy for
something instantiable, don't you already know the non-abstract
class of that something?
<br>
</blockquote>
<br>
<br>
No we don't, that file may not have been loaded/created yet. For
example we are loading a bunch of existing XML files that may
contain keys (with no type info) for elements in files we have not
processed yet. Happily the fact that proxies do not have to be
resolved allows us to handle this case.
<br>
</blockquote>
I see.<br>
<blockquote cite="mid:ke63c5$jbu$1@xxxxxxxxe.org" type="cite">
<br>
<br>
Quote:
<br>
<blockquote type="cite">&gt; Is there another approach? You need
to determine a concrete subclass of the abstract class. That's
why in an XMI serialization there will always be an xsi/xmi type
on such a proxy reference...
<br>
</blockquote>
<br>
[quote]Note that, although it's quite odd, it's not necessary that
the proxy will resolve to an object that's a subclass of the
proxy, so you could choose any arbitrary concrete subclass for the
proxy. But as I suggested with my previous question, it seems odd
that you'd know the proxy URI but not know the type of the target
for that URI...
<br>
<br>
Thanks, we were wondering about this approach. It will let us
avoid modifying the metamodel, but I guess we will need to be more
careful when working with proxies. Actually, we have already
figured out we need to be careful anyway since it seems if a
resolve fails the instance just returns nil for all its features
rather than throwing an error. <br>
</blockquote>
Yes, generally a proxy has no populated features and carries only
the proxy URI.<br>
<blockquote cite="mid:ke63c5$jbu$1@xxxxxxxxe.org" type="cite">Quote:
<br>
<blockquote type="cite">&gt; On the surface I don't see why we
can't have a proxy object of the &gt; abstract class's type that
will resolve to a concerete class type. It's not that you can't
have one. The problem is, just as an in Java, if you have an
abstract class X, you can do "new x()", and you can't even do it
reflectively.
<br>
</blockquote>
<br>
<br>
Sorry, I'm missing the difference between "can't have one" and
"can't create one". Are they not one and the same in this case or
am I missing something?
<br>
</blockquote>
Sorry, I meant you <b>cannot </b>do new X(). <br>
<blockquote cite="mid:ke63c5$jbu$1@xxxxxxxxe.org" type="cite">
<br>
At a theory level, we are not trying to instantiate the target
instance, we are trying to instantiate its proxy which is
practically possible in many other proxy frameworks. </blockquote>
Yes, such as Java dynamic proxies, but in that case, it's also not
possible to reuse some existing base class. I did investigate using
Java dynamic proxies to support this kind of thing for EMF, but it's
complicated by the fact all such objects also have to implement the
full InternalEObject API and must do so without extending
BasicEObjectImpl . Proxies for bidirectional references would have
to properly implement that API. I looked at how to do that by
delegation, but then you get into problems with == being used in the
framework for testing object equality always via identity. Not
much good came of it...<br>
<blockquote cite="mid:ke63c5$jbu$1@xxxxxxxxe.org" type="cite">As
you mentioned, even the EMF recognizes that its choice of proxy
type is just a guess since it can change (and easily could since
they are in different files).
<br>
</blockquote>
No, I wouldn't characterize it that way. When we serialize, we
write out a proxy URI when we know we'll need one during
deserialization. It's not a guess, it's exactly the type of the
referenced thing.<br>
<blockquote cite="mid:ke63c5$jbu$1@xxxxxxxxe.org" type="cite">
<br>
Quote:
<br>
<blockquote type="cite">&gt; Since EReference attributes don't
contain type information this &gt; doesn't seem to be a
requirement in the serialization format either.
<br>
As I mentioned above, the serialization will always specify an
xsi:type in these cases because the actual object will be a
concrete subclass and creating a proxy requires that
information.
<br>
</blockquote>
<br>
<br>
And if the root class isn't abstract then EMF doesn't generate the
xsi:types, further underscoring that EMF doesn't need them for
resolving </blockquote>
It needs them for creating a proxy. There might not even be a
concrete subclass within any models known at that point, so it
can't pick some arbitrary guessed type...<br>
<blockquote cite="mid:ke63c5$jbu$1@xxxxxxxxe.org" type="cite">-
it just needs them to get around the limitation on instantiating
the abstract class instances (even as proxies). </blockquote>
Yes.<br>
<blockquote cite="mid:ke63c5$jbu$1@xxxxxxxxe.org" type="cite">Still,
I can understand if there are assumptions in the implementation
that don't expect an abstract instance to exist even as a proxy.
<br>
</blockquote>
Certainly something like EcoreUtil.copy would have problems with
that. That's why I didn't suggest using new MyAbstractClass() {
/*stub methods*/ }, because it would definitely be odd for any
object x if x.eClass().isAbstract() is true.<br>
<blockquote cite="mid:ke63c5$jbu$1@xxxxxxxxe.org" type="cite">
<br>
Thanks! It's very helpful to understand the underlying logic.
<br>
<br>
</blockquote>
You're welcome. It is kind of an annoying limitation, but one for
which there appear to be no clean solutions.<br>
<blockquote cite="mid:ke63c5$jbu$1@xxxxxxxxe.org" type="cite">dave
<br>
<br>
<br>
</blockquote>
<br>
</body>
</html>]]>Ed Merks2013-01-28T15:20:11-00:00Re: Create proxy object for abstract reference typehttps://www.eclipse.org/forums/index.php/mv/msg/452171/1005761/#msg_1005761
.