eclipse-sirius / sirius-emf-json

JSON-based EMF Resource implementation - part of Eclipse Sirius
https://eclipse.dev/sirius/sirius-web.html
Eclipse Public License 2.0
5 stars 10 forks source link

Support Metamodel migration, POJO datatype and feature serialization ordering #22

Closed vrichard12 closed 1 month ago

vrichard12 commented 8 months ago

This issue addresses the following subjects:

sbegaudeau commented 7 months ago
vrichard12 commented 7 months ago
sbegaudeau commented 7 months ago

If you have a meta model with a custom datatype which can be an enum or not, for example in the official library sample from EMF:

There are countless of metamodels out there that are handling by themselves how to save/load the value of their datatypes, here is one case from UML for example. If you define a custom datatype in your meta model, you are in charge of its serialization/deserialization by overriding the relevant methods in your factory XxxFactoryImpl#createYyyFromString and XxxFactory#convertYyyToString. By default, EMF cannot do much more than object.toString() to save the object of course.

We cannot break the serialization of all those metamodels

vrichard12 commented 7 months ago

You're so right! Thank you for this feedback. The solution should involve overriding the fromString and toString methods, that's all. I'll come back to you later.

vrichard12 commented 7 months ago

Hi Stephane,

Actually it is not that simple because EFactory.convertToString() is called in the existing GsonEObjectSerializer.serializeEDataType() method, which is supposed to return a JsonElement and not a String. In addition, I think the factory should be resource type agnostic.

What was initially done in GsonEObjectSerializer.serializeEDataType() was to instantiate a JsonPrimitive with the return value of EFactory.convertToString(). This is fine as long as we are only dealing with primitive types, but when it comes to POJO, if convertToString() returns a json string then do we need to deserialize it into a JsonElement before returning it? I don't think so. This would impose that convertToString() returns a json string, which would break the resource type agnostic principle for the EFactory. There is no room for customizing the way a POJO DataType is serialized to a json string in the EFactory. If the EFactory.convertToString() is overridden, that's fine, and I agree that the overridden value should be used. But then its value must be treated as a JsonPrimitive. We cannot assume that the returned value is a consistent json string. It is the responsibility of the JsonResource to generate a valid Json structure.

Therefore, we have to find a way to detect that the EAttributeType is a POJO datatype, and that the convertToString() has not been overridden to generate a JsonTree in this case. Any other case must be treated as a primitive type value.

Identifying if the EAttributeType is a POJO datatype is done by testing if the instance class of the EAttributeType is not null because every other case of primitive types and enumeration has been handled in GsonEObjectSerializer.serializeEAttribute(). And testing that convertToString() has not been overridden is done with the test value.toString().equals(stringValue).

I have updated the commit accordingly, please take a look when you get a chance.