Workaround for limitations of generics #95
Replies: 1 comment
-
|
This looks AI generated. It's beyond my capacity to deal with high volume AI content. I think there will always be limitations if the type must be inferred from some "type binding" information of some container arbitrarily higher up in the containment chain. Even there the type's details can depend recursively on type parameters that turn must be resolved via some known "type binding" information even higher in the containment chain. This looks to me like a can of worms where the worms will never stay in the can. In any case, it must always be possible to serialize and deserialize B in isolation of the container, e.g., with cross resource containment references, where the container might to be loaded from a different resource separately from B an hence only a proxy is available, or just in general that any instance, in isolation, can be serialized or deserialized. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I encountered a limitation when using generic type parameters (
ETypeParameter) withEAttributein Ecore models.The issue manifests when class
A<T>contains a reference to classB<T>, whereBhas anEAttributeof typeT.In that case, the
EAttribute'seTyperesolves toEJavaObjectat runtime.During serialisation and deserialisation (both XML and binary formats), EMF cannot determine the effective
EType, causing the value to be serialised as bytes as if it was an instance of java.lang.Object.Simple Reproduction Case
Given this Ecore model:
When serialising
Document.a.b.valuewith value42:<value>0x2A</value>(using Hex's string conversion from factory)<value>ACED0005737200116A6176612E6C616E672E496E746567657212E2A0A4F781873802000149000576616C7565787200106A6176612E6C616E672E4E756D62657286AC951D0B94E08B02000078700000002A</value>(using EJavaObject/Integer default)Analysis
eGenericType, not through the standardeTypeThis results in values being stored/loaded as strings or incorrect types, breaking roundtrip serialisation.
Root Cause
The issue stems from the temporal ordering of EMF's deserialisation process. During XML loading,
setValueis called before the object is added to the containment tree, preventing proper type resolution:When
EAttributehaseGenericTypewith aneTypeParameter, the resolution chain is:eClass()defineseTypeParameters(e.g.,<T extends EDataType>)EReferencehaseGenericTypewitheTypeArguments(e.g.,Container<Integer>)EType(Integer)But during deserialisation, the object isn't in the containment tree yet, so the resolution fails.
Workaround
A post-processing approach that resolves generic types after the containment tree is complete:
Implementation
Four extension classes:
1. XML Deserialisation - Store Strings Temporarily
2. XML Deserialisation - Post-Process After Loading
3. XML Serialisation - Resolve During Save
4. Binary Format Support
Usage
Rationale
Why Post-Processing?
Decided on post-processing over modifying EMF's core serialisation because:
Complexity
Design Decisions
EFactory.createFromString()for values coming in a strings during XML LoadT extends Bound(Liskov Substitution Principle)Limitations
EAttributewithEDataTypegeneric parameters (notEReferencewith genericEClass)EDataTypehasinstanceClassNamedefined for conversionEList<T>)Open Questions
Through my current solution is an external workaround, I am wondering:
Would this type of functionality be valuable in EMF core, or is the workaround preferable?
Implementation Location: If this were to be included, where would it best fit?
Are there more straight forward ways, which I have missed, to handle this? I thought about:
XMLHandlerto delay type conversion (too invasive).EFactory/EClassinorg.eclipse.emf.ecore(too invasive).If deemed a valuable contribution to EMF core, should this handle more than just
EAttributewithEDataTypeparameters? I'm thinking:EReferencetypes,isMany := true´ generics such asEList`?I would happy to refactor this implementation to match EMF's standards if there's interest in incorporating it.
I primarily wanted to share my approach and get feedback from the community.
Thank you @merks for your time and for maintaining such a powerful framework!
Beta Was this translation helpful? Give feedback.
All reactions