Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Single references of EObject type in Dynamic Model
Single references of EObject type in Dynamic Model [message #1814131] Wed, 04 September 2019 13:35 Go to next message
Christian Damus is currently offline Christian DamusFriend
Messages: 1270
Registered: July 2009
Location: Canada
Senior Member

Hi,

I've run into a situation that looks like an inconsistency between the behaviour of dynamic models and generated models, but I'm not sure.

I've got an Ecore model with an EClass that has a single reference of EObject type. In some pseudolanguage:

package xyz {
  class Foo {
    ref someObject[1] : EObject
  }
}


If I generate the code for xyz, I can create a Foo and assign any EObject of any kind to the someObject reference. That object may be generated itself or a dynamic EObject; it doesn't matter. Serialization and deserialization works, all is good.

However, if instead I don't generate xyz but just use dynamic EMF to create an instance of Foo, then the EStructuralFeatureImpl::InternalSettingDelegateSingleEObject::dynamicSet(...) method requires that any value assigned to the someObject reference have EObject as an explicit super type, otherwise a ClassCastException is thrown.

Is this intended? Because for a statically-generated model, the Java types in the API let us assign anything because by default models are generated with the EMF interfaces declared publicly. But Java ordinarily wouldn't let me assign an object of a class that doesn't publicly implement EObject, although in that case I have the work-around of a cast because internally there is no other type checking as in the dynamic setting implementation.

So, it seems as though it is intended that references of type EObject should be used only with models whose EClasses explicitly extend EObject, but does anyone ever really do that? Is it a supported/recommended pattern to extend EObject? Is there an inconsistency here between the behaviour of generated and dynamic models?

It could be easy enough in the dynamic setting implementation to have a special case for a reference of EObject type. And I think multiple-valued references don't even have a type check like this? (or I don't see it).

Anyways, I'd like to know what the EMF team/community thinks about this.

Thanks,
Christian
Re: Single references of EObject type in Dynamic Model [message #1814134 is a reply to message #1814131] Wed, 04 September 2019 14:21 Go to previous messageGo to next message
Ed Willink is currently offline Ed WillinkFriend
Messages: 7675
Registered: July 2009
Senior Member
Hi Chrisitian

I think that may find some commonality with https://bugs.eclipse.org/bugs/show_bug.cgi?id=532561 where I initially thought the same as you, hit legacy issues with a change and eventually concluded/agreed that the 'better' functionality was invalid.

Regards

Ed Willink
Re: Single references of EObject type in Dynamic Model [message #1814148 is a reply to message #1814134] Wed, 04 September 2019 18:17 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33223
Registered: July 2009
Senior Member
I assume this depends on which EObject is used, and the pseudo language doesn't tell me that. I.e., the runtime instance (EcorePackage.Liiterals.EObject) or the development time instance as loaded from platform:/plugin/org.ecipse.emf.ecore/model/Ecore.ecore. No, it's not generally expected to extend EObject explicitly in the model. But if your model is using the development time EObject, then yes, the framework will check that the instance is explicitly a subclass of that.

Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Single references of EObject type in Dynamic Model [message #1814155 is a reply to message #1814148] Wed, 04 September 2019 21:57 Go to previous messageGo to next message
Christian Damus is currently offline Christian DamusFriend
Messages: 1270
Registered: July 2009
Location: Canada
Senior Member

Hi, Ed, Ed,

Thanks for the replies. Indeed, there do seem to be a few cases where applications run into trouble with different behaviour in dynamic versus generated models where conformance to EObject type is usually satisfied Java-wise in generated code but not in dynamic instances because the model doesn't actually prescribe EObject conformance.

Ed M., I wasn't aware that there could be different behaviour of the run-time when a model specified the EClass type of an EReference using the "development-time" class (via platform:/ URI) versus the "run-time" class (via namespace URI). That seems surprising, as in both cases the Genmodel references the same dependency Genmodel (in my case, Ecore.genmodel for the EObject reference).

I think I left out some context from this private client application. What we have is a situation where an EClass from a generated model has a single containment reference of EObject type, and that referenced EObject is any kind of thing from our application-specific model, which also (normally) is generated to code but where none of the EClasses explicitly inherit EObject (which I'm glad to understand is the expected norm). The specific case is the Data Template model from EMF Forms: a Template contains an 'instance' that is anything from any of our application models, and templates are used by the EMF Forms editors to quickly add objects of varying complexity to the tree of stuff being edited. Although in our application, both the Template model and the models describing the things that templates will contain are all generated, these models evolve rapidly and schema migration of resources is managed via Edapt. This is where the dynamic EObjects come into play: Edapt migration loads a resource in an older schema by reconstructing the older version of the EPackage and using the dynamic factory to load the content. Then it can create the migrated content using the generated packages/factories in the current version of the schema, copy the data over from the dynamic instances, and save the result.

So, in my application, if I need to migrate a Template (containing a pre-fab instance of my application model) from an old schema version to the current version, Edapt is going to have to be able to create a dynamic EObject for the Template and also for the thing that it contains via the Template::instance reference (of EObject type). But that falls down on the check in the setting delegate, where dynamicSet(...) first checks

      if (newValue != null && !eClass.isInstance(newValue))
      {
        throw 
          new ClassCastException
            ("The value of type '" + 
               (newValue instanceof EObject ? ((EObject)newValue).eClass().toString() : newValue.getClass().toString()) + 
               "' must be of type '" + eClass + "'");
      }


Because the eClass of the feature is EObject, only a newValue whose eClass() explicitly inherits EObject will pass this check. The result is that we can't migrate templates because none of our application models' EClasses inherit EObject. In all other respects, the templates work fine because the generated code always works: the objects always really are Java-wise instances of EObject even if Ecore-wise they aren't. It would be nice if there were a special case here for EObject references, something like:

      if (newValue != null && !eClass.isInstance(newValue)
            && (eClass != EcorePackage.Literals.EOBJECT || !(newValue instanceof EObject)))
      {
        throw ... 



I don't know if this explanation of my scenario makes sense, but it seems that this dynamic behaviour of references of EObject type can snag any application that like ours uses Edapt for schema migration with EMF Forms templates. There's nothing that Edapt can do to help; there's no real alternative to dynamic EMF for its job. And I don't know how the template model can express this containment of "any kind of object" except by an EReference of EObject type. So, the situation seems to be stuck there.

Anyways, thanks as always for your help. If you have further insights, that's great, otherwise no worries.

Christian
Re: Single references of EObject type in Dynamic Model [message #1814160 is a reply to message #1814155] Thu, 05 September 2019 07:17 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33223
Registered: July 2009
Senior Member
In the end, the eClass.isInstance(newValue) calls org.eclipse.emf.ecore.impl.EClassifierImpl.isInstance(Object), which, if there is an instanceClass just does a Class.isInstance. If there is not, it calls org.eclipse.emf.ecore.impl.EClassifierImpl.dynamicIsInstance(EObject), which is specialized by org.eclipse.emf.ecore.impl.EClassImpl.dynamicIsInstance(EObject), which does a super type test. So from what you're telling me, the eClass in eClass.isInstance(newValue), must not literally be EPackage.Literals.EObject.

This problem can (and should, if the difference in behavior is important) be avoided if you (EMF Forms I suppose) use the nsURI-reference-based EObject in the model definition(just as one normally does for the EDataTypes from Ecore, where it's also important that you end up using EcoreFactoryImpl for creating/converting the values). It doesn't seem generally a good idea to try to build in anywhere special knowledge and special behavior for the "special" EObject class from the development time Ecore model; there can be thousands of them in any given JVM, and there's no guarantee that any of them really are EObject and not some completely modified new design prototyped instance that just looks like it is or should be considered the same as EcorePackage.Literals.EObject. You'll noticed in the Ecore editor, for example, that EObject is always visible for use in an EReference and is serialized as eType="ecore:EClass http://www.eclipse.org/emf/2002/Ecore#//EObject" so generally the editor is directing/encouraging the direct use of EPackage.Literals.EObject..


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: Single references of EObject type in Dynamic Model [message #1814198 is a reply to message #1814160] Thu, 05 September 2019 14:11 Go to previous messageGo to next message
Christian Damus is currently offline Christian DamusFriend
Messages: 1270
Registered: July 2009
Location: Canada
Senior Member

Hi, Ed,

It is clear that I need to better understand the different run-time behaviour of models that reference EObject by development-time URIs versus NS URI. You are correct in your surmise that the EMF Forms Template model uses the platform:/resource URI for Ecore.ecore. I'll raise us a bug for that. I had thought that the EMF run-time has URI mappings to convert the platform URIs to the NS URIs for registered packages so that in the end you always get the registered package either way, but of course that doesn't make sense because then I wouldn't see the development-time resource in the Ecore Editor!

I also hadn't realized that the EClass::isInstance(...) method doesn't always just looks for itself in the eAllSuperTypes of the object's eClass. Makes sense that it will use the instanceClass when it can.

So, this really helpful.

Thanks again!
Christian
SOLVED [Re: Single references of EObject type in Dynamic Model] [message #1814208 is a reply to message #1814198] Thu, 05 September 2019 15:48 Go to previous messageGo to next message
Christian Damus is currently offline Christian DamusFriend
Messages: 1270
Registered: July 2009
Location: Canada
Senior Member

Hi, Ed,

I can confirm that changing the HREF URI for the reference to the EObject class in the EMF Forms template model from development-time resource URI to NS URI fixes my Edapt migration scenario. The dynamic implementation used by Edapt is able to assign the Template::instance feature of EObject type!

Thanks,
Christian
Re: SOLVED [Re: Single references of EObject type in Dynamic Model] [message #1814210 is a reply to message #1814208] Thu, 05 September 2019 16:47 Go to previous message
Ed Merks is currently offline Ed MerksFriend
Messages: 33223
Registered: July 2009
Senior Member
That's good to hear. Of course when a model is generated, the generated model refers to EcorePackage.Literals.EObject, regardless of which variant of that was referenced by development time version, so it's easy not to notice/realize any type of difference. But if that same model is to be used as a dynamic model, it definitely makes a difference.

Ed Merks
Professional Support: https://www.macromodeling.com/
Previous Topic:How to create genmodel from ecore programmatically without using headless invocation/eclipse plugins
Next Topic:[CDO] CDOStoreUnorderedEList invalidates index of RemoveCommand during undo
Goto Forum:
  


Current Time: Sat Oct 05 10:37:38 GMT 2024

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

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

Back to the top