diff --git a/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/resource/JsonResource.java b/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/resource/JsonResource.java index 440b071..89057c1 100644 --- a/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/resource/JsonResource.java +++ b/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/resource/JsonResource.java @@ -16,6 +16,7 @@ import java.io.InputStream; import java.io.OutputStream; +import java.util.Comparator; import java.util.Map; import org.eclipse.emf.common.util.URI; @@ -418,6 +419,12 @@ interface IEObjectHandler { */ String OPTION_ID_MANAGER = "OPTION_ID_MANAGER"; //$NON-NLS-1$ + /** + * An option to provide a {@link Comparator} of {@link EStructuralFeature} to determine the order of the attributes + * in the serialized Json. + */ + Object OPTION_SAVE_FEATURES_ORDER_COMPARATOR = "OPTION_SAVE_FEATURES_ORDER_COMPARATOR"; //$NON-NLS-1$ + /** * Associate an ID to the {@link EObject}. * diff --git a/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/utils/GsonEObjectSerializer.java b/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/utils/GsonEObjectSerializer.java index 86ea5d2..87442ab 100644 --- a/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/utils/GsonEObjectSerializer.java +++ b/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/utils/GsonEObjectSerializer.java @@ -24,12 +24,14 @@ import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Collections; +import java.util.Comparator; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.stream.Collectors; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.EMap; @@ -871,10 +873,18 @@ private JsonElement createJsonHeader() { * The EObject to serialize * @return A JsonObject containing all the properties of the given object */ + @SuppressWarnings("unchecked") private JsonObject serializeEAllStructuralFeatures(EObject eObject) { JsonObject properties = new JsonObject(); EClass eClass = eObject.eClass(); - EList eAllStructuralFeatures = eClass.getEAllStructuralFeatures(); + List eAllStructuralFeatures = eClass.getEAllStructuralFeatures(); + + Object orderFeatures = this.options.get(JsonResource.OPTION_SAVE_FEATURES_ORDER_COMPARATOR); + if (orderFeatures instanceof Comparator) { + eAllStructuralFeatures = eAllStructuralFeatures.stream() // + .sorted((Comparator) orderFeatures) // + .collect(Collectors.toList()); + } for (EStructuralFeature eStructuralFeature : eAllStructuralFeatures) { if (this.shouldSerialize(eObject, eStructuralFeature)) { diff --git a/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/unit/save/SerializeOptionsTests.java b/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/unit/save/SerializeOptionsTests.java index 176869e..ba51bfe 100644 --- a/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/unit/save/SerializeOptionsTests.java +++ b/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/unit/save/SerializeOptionsTests.java @@ -25,6 +25,7 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; +import java.util.Comparator; import java.util.Map; import org.eclipse.emf.common.util.BasicEList; @@ -450,4 +451,23 @@ public void postLoad(JsonResource resource, InputStream inputStream, Map l this.testSave("SimpleModelWithOnlyDefaultValueForResourceHandlerPreSavingTest.xmi"); //$NON-NLS-1$ } + + /** + * Test the serialization with feature order comparator. + */ + @Test + public void testSerializationWithFeatureOrderComparator() { + // A comparator to sort the feature on their name length. + Comparator featuresComparator = new Comparator() { + @Override + public int compare(EStructuralFeature o1, EStructuralFeature o2) { + return o1.getName().length() - o2.getName().length(); + } + }; + + this.options.put(JsonResource.OPTION_SAVE_FEATURES_ORDER_COMPARATOR, featuresComparator); + this.testSave("TestSerializationWithFeatureOrderComparator.xmi"); //$NON-NLS-1$ + + } + } diff --git a/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/serializeoptions/TestSerializationWithFeatureOrderComparator.json b/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/serializeoptions/TestSerializationWithFeatureOrderComparator.json new file mode 100644 index 0000000..63e7c46 --- /dev/null +++ b/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/serializeoptions/TestSerializationWithFeatureOrderComparator.json @@ -0,0 +1,22 @@ +{ + "json": { + "version": "1.0", + "encoding": "utf-8" + }, + "ns": { + "nodes": "http://www.obeo.fr/EMFJson" + }, + "schemaLocation": { + "http://www.obeo.fr/EMFJson": "../../../nodes.ecore" + }, + "content": [ + { + "eClass": "nodes:NodeSingleValueAttribute", + "data": { + "singleIntAttribute": 12, + "singleStringAttribute": "String value", + "singleBooleanAttribute": true + } + } + ] +} \ No newline at end of file diff --git a/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/serializeoptions/TestSerializationWithFeatureOrderComparator.xmi b/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/serializeoptions/TestSerializationWithFeatureOrderComparator.xmi new file mode 100644 index 0000000..19bde55 --- /dev/null +++ b/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/serializeoptions/TestSerializationWithFeatureOrderComparator.xmi @@ -0,0 +1,10 @@ + +