From 507db59a9d75d5696eb1266c9ba6cd8c18c8b855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20B=C3=A9gaudeau?= Date: Thu, 7 Mar 2024 11:02:32 +0100 Subject: [PATCH] [32] Add the ability to retrieve information during the serialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: https://github.com/eclipse-sirius/sirius-emf-json/issues/32 Signed-off-by: Stéphane Bégaudeau --- .../sirius/emfjson/resource/JsonResource.java | 71 +++++++++++++++++++ .../emfjson/utils/GsonEObjectSerializer.java | 19 +++-- .../tests/internal/AbstractEMFJsonTests.java | 22 ++++++ .../NonContainmentReferencesSaveTests.java | 8 +++ 4 files changed, 116 insertions(+), 4 deletions(-) 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 89057c1..84b08ef 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 @@ -22,6 +22,7 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; @@ -425,6 +426,75 @@ interface IEObjectHandler { */ Object OPTION_SAVE_FEATURES_ORDER_COMPARATOR = "OPTION_SAVE_FEATURES_ORDER_COMPARATOR"; //$NON-NLS-1$ + /** + * An option to provide an ISerializationListener. + */ + String OPTION_SERIALIZATION_LISTENER = "OPTION_SERIALIZATION_LISTENER"; //$NON-NLS-1$ + + /** + * Used to listen to various events during the serialization. + * + * @author Stephane Begaudeau + */ + interface ISerializationListener { + + /** + * Called when an entry is added to the namespace header. + * + * @param nsPrefix + * The prefix of the ePackage added + * @param nsURI + * The URI of the ePackage added + */ + void onNsHeaderEntryAdded(String nsPrefix, String nsURI); + + /** + * Called when an object is serialized. + * + * @param eObject + * The EObject serialized + * @param jsonElement + * The serialization of the EObject + */ + void onObjectSerialized(EObject eObject, JsonElement jsonElement); + + /** + * Called when a proxy to an object located in another resource has been created. + * + * @param eObject + * The object for which the URI is created + * @param eReference + * The reference containing the object + * @param uri + * The uri created + */ + void onCrossReferenceURICreated(EObject eObject, EReference eReference, String uri); + + /** + * Implementation of the listener which does nothing. + * + * @author Stephane Begaudeau + */ + class NoOp implements ISerializationListener { + + @Override + public void onNsHeaderEntryAdded(String nsPrefix, String nsURI) { + // Do nothing + } + + @Override + public void onObjectSerialized(EObject eObject, JsonElement jsonElement) { + // Do nothing + } + + @Override + public void onCrossReferenceURICreated(EObject eObject, EReference eReference, String uri) { + // Do nothing + } + + } + } + /** * Associate an ID to the {@link EObject}. * @@ -434,4 +504,5 @@ interface IEObjectHandler { * the id */ void setID(EObject eObject, String id); + } 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 87442ab..a22cec8 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 @@ -65,6 +65,7 @@ import org.eclipse.sirius.emfjson.resource.JsonResource; import org.eclipse.sirius.emfjson.resource.JsonResource.EStructuralFeaturesFilter; import org.eclipse.sirius.emfjson.resource.JsonResource.IEObjectHandler; +import org.eclipse.sirius.emfjson.resource.JsonResource.ISerializationListener; import org.eclipse.sirius.emfjson.resource.JsonResource.ResourceEntityHandler; import org.eclipse.sirius.emfjson.resource.exception.DanglingHREFException; @@ -127,6 +128,8 @@ public class GsonEObjectSerializer implements JsonSerializer> { */ private IEObjectHandler eObjectHandler; + private ISerializationListener serializationListener; + /** * The constructor. * @@ -166,7 +169,11 @@ public GsonEObjectSerializer(Resource resource, Map options) { this.helper.setExtendedMetaData(this.extendedMetaData); } - this.eObjectHandler = (JsonResource.IEObjectHandler) serializedOptions.get(JsonResource.OPTION_EOBJECT_HANDLER); + this.eObjectHandler = (IEObjectHandler) serializedOptions.get(JsonResource.OPTION_EOBJECT_HANDLER); + this.serializationListener = (ISerializationListener) serializedOptions.get(JsonResource.OPTION_SERIALIZATION_LISTENER); + if (this.serializationListener == null) { + this.serializationListener = new ISerializationListener.NoOp(); + } this.declareSchemaLocation = Boolean.TRUE.equals(options.get(JsonResource.OPTION_SCHEMA_LOCATION)); @@ -236,6 +243,8 @@ private JsonElement createData(EObject eObject) { this.eObjectHandler.processSerializedContent(jsonElement, eObject); } + this.serializationListener.onObjectSerialized(eObject, jsonElement); + return jsonElement; } @@ -835,6 +844,7 @@ private JsonElement createNsHeader() { List nsPrefixes = this.helper.getPrefixes(ePackage); for (String nsPrefix : nsPrefixes) { jsonObject.add(nsPrefix, new JsonPrimitive(nsURI)); + this.serializationListener.onNsHeaderEntryAdded(nsPrefix, nsURI); } } } @@ -1381,7 +1391,7 @@ private JsonElement serializeMultipleNonContainmentEReference(EObject eObject, E break; case CROSS_DOC: if (value != null) { - jsonArray.add(new JsonPrimitive(this.saveHref(value, null))); + jsonArray.add(new JsonPrimitive(this.saveHref(value, eReference))); } break; default: @@ -1495,6 +1505,7 @@ private String saveHref(EObject object, EReference eReference) { // TODO: element Handler if statement : look at XMLSaveImpl line 2308 value += href; } + this.serializationListener.onCrossReferenceURICreated(object, eReference, value); return value; } @@ -1540,8 +1551,8 @@ private int docKindSingle(EObject eObject, EReference eReference) { } /** - * Return the the URI fragment if the pointed resource URI schema is the same of the Resource URI schema. Return the - * all URI otherwise. + * Return the URI fragment if the pointed resource URI schema is the same of the Resource URI schema. Return the all + * URI otherwise. * * @param pointedResourceUri * the pointed resource URI diff --git a/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/AbstractEMFJsonTests.java b/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/AbstractEMFJsonTests.java index 5ff1c6a..589d625 100644 --- a/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/AbstractEMFJsonTests.java +++ b/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/AbstractEMFJsonTests.java @@ -34,6 +34,7 @@ import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; +import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; @@ -67,6 +68,11 @@ public abstract class AbstractEMFJsonTests { */ protected Map options = new HashMap(); + /** + * Data saved by the serialization listener. + */ + protected Map listenerData = new HashMap(); + /** * Returns the path of the folder containing the models used during the tests of this class. * @@ -82,6 +88,8 @@ public abstract class AbstractEMFJsonTests { * The name of the resource to save */ protected void testSave(String resourceName) { + this.listenerData.clear(); + Resource modelResource = this.getModelResource(resourceName, true); ResourceSet resourceSet = new ResourceSetImpl(); @@ -104,6 +112,20 @@ protected void testSave(String resourceName) { this.options.put(JsonResource.OPTION_PRETTY_PRINTING_INDENT, JsonResource.INDENT_2_SPACES); this.options.put(JsonResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE); + JsonResource.ISerializationListener serializationListener = new JsonResource.ISerializationListener.NoOp() { + @Override + public void onNsHeaderEntryAdded(String nsPrefix, String nsURI) { + AbstractEMFJsonTests.this.listenerData.put("onNsHeaderEntryAdded", nsPrefix + " - " + nsURI); //$NON-NLS-1$//$NON-NLS-2$ + } + + @Override + public void onCrossReferenceURICreated(EObject eObject, EReference eReference, String uri) { + AbstractEMFJsonTests.this.listenerData.put("onCrossReferenceURICreated", uri); //$NON-NLS-1$ + } + }; + + this.options.put(JsonResource.OPTION_SERIALIZATION_LISTENER, serializationListener); + resource.save(outputStream, this.options); String json = new String(outputStream.toByteArray(), Charset.forName("utf-8")); //$NON-NLS-1$ diff --git a/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/unit/save/NonContainmentReferencesSaveTests.java b/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/unit/save/NonContainmentReferencesSaveTests.java index 1b1656f..133b115 100644 --- a/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/unit/save/NonContainmentReferencesSaveTests.java +++ b/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/unit/save/NonContainmentReferencesSaveTests.java @@ -70,6 +70,8 @@ protected String getRootPath() { @Test public void testSaveSingleValuedEReference() { this.testSave("NodeSingleValueEReference.xmi"); //$NON-NLS-1$ + + Assert.assertEquals(this.listenerData.get("onNsHeaderEntryAdded"), "nodes - http://www.obeo.fr/EMFJson"); //$NON-NLS-1$ //$NON-NLS-2$ } /** @@ -105,6 +107,8 @@ public void testSaveLibraryWithBookReferencingItsOwnLibrary() { @Test public void testSaveLibraryWithBookReferencingLibraries() { this.testSave("TestLibraryWithBookReferencingLibraries.xmi"); //$NON-NLS-1$ + + Assert.assertEquals(this.listenerData.get("onNsHeaderEntryAdded"), "extlib - http:///org/eclipse/emf/examples/library/extlibrary.ecore/1.0.0"); //$NON-NLS-1$//$NON-NLS-2$ } /** @@ -123,6 +127,8 @@ public void testSaveLibraryWithExternalBookReferencingBranchLibrary() { @Test public void testSaveLibraryWithExternalBookReferencingLibraries() { this.testSave("TestLibraryWithExternalBookReferencingLibraries_Book.xmi"); //$NON-NLS-1$ + + Assert.assertEquals(this.listenerData.get("onCrossReferenceURICreated"), "TestLibraryWithExternalBookReferencingLibraries_Library.xmi#/0/@branches.0"); //$NON-NLS-1$//$NON-NLS-2$ } /** @@ -140,6 +146,8 @@ public void testSaveLibraryWithExternalBookReferencingLibrary() { @Test public void testSaveExternalMultiNonContainmentReferences() { this.testSave("TestExternalMultiNonContainmentReferences.ecore"); //$NON-NLS-1$ + + Assert.assertEquals(this.listenerData.get("onCrossReferenceURICreated"), "../../../nodes.ecore#//NodeMultipleCustomDataType"); //$NON-NLS-1$//$NON-NLS-2$ } /**