-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[22] Support Metamodel migration, POJO datatype and feature serialization ordering #21
[22] Support Metamodel migration, POJO datatype and feature serialization ordering #21
Conversation
fixes #22 |
@@ -19,5 +19,5 @@ Import-Package: javax.xml.bind;version="0.0.0", | |||
org.eclipse.emf.ecore.resource;version="0.0.0", | |||
org.eclipse.emf.ecore.resource.impl;version="0.0.0", | |||
org.eclipse.emf.ecore.util;version="0.0.0" | |||
Require-Bundle: javax.xml.bind |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you removing and then adding back java.xml.bind
and why remove its version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't remove it, I added it. It was missing and it was blocking the build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private static final List<EDataType> ECORE_PACKAGE_DATA_TYPES = Arrays.asList(EcorePackage.eINSTANCE.getEString(), EcorePackage.eINSTANCE.getEBoolean(), EcorePackage.eINSTANCE.getEBooleanObject(), | ||
EcorePackage.eINSTANCE.getEInt(), EcorePackage.eINSTANCE.getEIntegerObject(), EcorePackage.eINSTANCE.getEBigDecimal(), EcorePackage.eINSTANCE.getEBigInteger(), | ||
EcorePackage.eINSTANCE.getEByte(), EcorePackage.eINSTANCE.getEByteArray(), EcorePackage.eINSTANCE.getEByteObject(), EcorePackage.eINSTANCE.getEChar(), | ||
EcorePackage.eINSTANCE.getECharacterObject(), EcorePackage.eINSTANCE.getEDate(), EcorePackage.eINSTANCE.getEDouble(), EcorePackage.eINSTANCE.getEDoubleObject(), | ||
EcorePackage.eINSTANCE.getEFloat(), EcorePackage.eINSTANCE.getEFloatObject(), EcorePackage.eINSTANCE.getELong(), EcorePackage.eINSTANCE.getELongObject(), | ||
EcorePackage.eINSTANCE.getEShort(), EcorePackage.eINSTANCE.getEShortObject()); | ||
|
||
/** | ||
* Tests if the given {@link EDataType} is a POJO. | ||
* | ||
* @param dataType | ||
* A {@link EDataType} to test | ||
* @return true if the given {@link EDataType} is not one of the {@link EcorePackage} DataTypes nor an | ||
* {@link EEnum}. | ||
*/ | ||
private boolean isPojo(EDataType dataType) { | ||
return !ECORE_PACKAGE_DATA_TYPES.contains(dataType) && // | ||
dataType.eClass() != EcorePackage.eINSTANCE.getEEnum() && // | ||
dataType.getInstanceClass() != null; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would we consider that if something is not from Ecore then we should not leverage the method EcoreUtil.createFromString
? Is there anything like that in XMIResource
? If not, I don't understand the need for an ad hoc serialization system in our code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
EcoreUtil.createFromString
does not handle json format. I don't see your point.
What would anything be like in XMIResource
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In XMI resource, you would have to implement the expected methods from EMF and you would not return XML data structure this way. But if done properly, your meta-model could work for every kind of resources, XMI, Json, binary, etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pull request mixes commits which look good from afar (I have not tested nor really reviewed them) and a couple of commits which are a bit odd for me at the moment. Such a big PR mixing various concerns is quite slow to integrate.
For the content that seems odd to me, I don't see why we would need a custom serialization mechanism on top of the EMF one nor why we should change the current behavior for datatypes.
As I said in the associated issue #22, before this evolution, the POJO serialization felt back to a toString() call, producing this kind of string: |
4505bc8
to
22f04b9
Compare
22f04b9
to
63ed710
Compare
I've merged 90% of the commits of this pull request as part of the pr #31 and performed the release of EMFJson 2.3.6. This way, we can continue our discussion regarding the last commit since I still have some issues with the code. |
9ee6461
to
17dc1c4
Compare
Hi Stéphane, To get everyone in agreement, I've set up an option to specify which POJO should be considered by Json serialization/deserialization ( You'll notice that I've also avoided calling Finally, I had to correct a behavior in |
@@ -425,6 +428,12 @@ interface IEObjectHandler { | |||
*/ | |||
Object OPTION_SAVE_FEATURES_ORDER_COMPARATOR = "OPTION_SAVE_FEATURES_ORDER_COMPARATOR"; //$NON-NLS-1$ | |||
|
|||
/** | |||
* Specify a {@link Function} returning {@link Boolean#TRUE} if a given {@link EDataType} should be serialized |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good remark from Gionatta. Prefer a Predicate that is designed for this need.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely yes! Thank you for the remark. I fixed that.
* @param eDataType | ||
* @return true if the given {@link EDataType} should be deserialized from a Json tree. | ||
*/ | ||
private boolean isEDataTypeSerializableInJson(EDataType eDataType) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isEDataTypeSerializableInJson
-> isSerializeEDataTypeInJson
if (this.isEDataTypeSerializableInJson(eAttribute.getEAttributeType())) { | ||
jsonElement = new Gson().toJsonTree(value); | ||
} else { | ||
if (stringValue == null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prefer checking null first like line 1046. It avoid letting the given Predicate manage this case (if any)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes you're right, the code will be cleaner like that. I fix that right now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
private boolean isEDataTypeSerializableInJson(EDataType eDataType) { | ||
@SuppressWarnings("unchecked") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isEDataTypeSerializableInJson
-> isSerializeEDataTypeInJson
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming "isSerializeEDataTypeInJson" suggests that the given EDataType is serializable and that, based on this assumption, tests whether the "Json" serialization is a valid target for serialization. I find this naming incorrect. I prefer to keep "isEDataTypeSerializableInJson", which says exactly what the test does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually you're right on one point. The test should not say "can" but "should". I propose to rename it "shouldEDataTypeBeSerializedInJson" which reflect the real intent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fixed the code accordingly.
4a427b6
to
4eb40c1
Compare
String stringValue = eFactoryInstance.convertToString(eAttribute.getEAttributeType(), value); | ||
|
||
if (stringValue == null) { | ||
stringValue = ""; //$NON-NLS-1$ | ||
jsonElement = JsonNull.INSTANCE; | ||
} else if (this.shouldEDataTypeBeSerializedInJson(eAttribute.getEAttributeType())) { | ||
jsonElement = new Gson().toJsonTree(value); | ||
} else { | ||
jsonElement = new JsonPrimitive(stringValue); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that shouldEDataTypeBeSerializedInJson()
should be called first, like:
if (this.shouldEDataTypeBeSerializedInJson(eAttribute.getEAttributeType())) {
jsonElement = new Gson().toJsonTree(value);
} else {
String stringValue = eFactoryInstance.convertToString(eAttribute.getEAttributeType(), value);
if (stringValue == null) {
jsonElement = JsonNull.INSTANCE;
} else {
jsonElement = new JsonPrimitive(stringValue);
}
}
It's the same beahviour of the eAttribute.isMany()
case above.
4eb40c1
to
36e85fa
Compare
Signed-off-by: Stéphane Bégaudeau <stephane.begaudeau@obeo.fr>
Addresses the following subjects:
Handling the renaming of EAttribute
Renaming of EAttribute is handled by the
ExtendedMetaData.getElement()
API. Examples of such a migration is provided in theorg.eclipse.sirius.emfjson.tests.internal.unit.load.ExtendedMetaDataAttributesLoadTests
test class.Handling a type change or a value change of an EAttribute
Changing the type or the value of an EAttribute is handled with the
JsonHelper.setValue()
API. Exemple of such migrations are provided in theorg.eclipse.sirius.emfjson.tests.internal.unit.load.JsonHelperDataLoadTests
test class.Support for Serialization / deserialization of POJO EDataType
Custom data types with instance type set to a POJO class are serialized to / deserialized from json. The corresponding tests are :
org.eclipse.sirius.emfjson.tests.internal.unit.load.DataTypeLoadTests.testLoadSingleValueAttributePojoDataType()
org.eclipse.sirius.emfjson.tests.internal.unit.load.DataTypeLoadTests.testLoadMultiValuedAttributePojoDataType()
org.eclipse.sirius.emfjson.tests.internal.unit.save.DataTypeSaveTests.testSaveSingleValueAttributePojoDataType()
org.eclipse.sirius.emfjson.tests.internal.unit.save.DataTypeSaveTests.testSaveMultiValuedAttributePojoDataType()
A comparator option on the JsonResource to determine the order in which features are serialized
org.eclipse.sirius.emfjson.tests.internal.unit.save.SerializeOptionsTests.testSerializationWithFeatureOrderComparator()