Skip to content

Commit

Permalink
[34] Add the ability to add or retreive custom data
Browse files Browse the repository at this point in the history
Bug: #34
Signed-off-by: Michaël Charfadi <[email protected]>
  • Loading branch information
mcharfadi committed Apr 4, 2024
1 parent 126649a commit 92bd112
Show file tree
Hide file tree
Showing 6 changed files with 275 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
package org.eclipse.sirius.emfjson.resource;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import java.io.InputStream;
import java.io.OutputStream;
Expand Down Expand Up @@ -495,6 +496,58 @@ public void onCrossReferenceURICreated(EObject eObject, EReference eReference, S
}
}

/**
* An option to provide an IJsonResourceProcessor.
*/
String OPTION_JSON_RESSOURCE_PROCESSOR = "OPTION_JSON_RESSOURCE_PROCESSOR"; //$NON-NLS-1$

/**
* Used to add data to be serialized in the document, or to retrieve data during deserialization.
*
* @author <a href="mailto:[email protected]">Michael Charfadi</a>
*/
interface IJsonResourceProcessor {

/**
* Called when a JsonResource is deserialized.
*
* @param resource
* The JsonResource that is deserialized
* @param jsonObject
* The root jsonObject
*/
void preDeserialization(JsonResource resource, JsonObject jsonObject);

/**
* Called when a JsonResource is serialized.
*
* @param resource
* The JsonResource that is serialized
* @param jsonObject
* The root jsonObject
*/
void postSerialization(JsonResource resource, JsonObject jsonObject);

/**
* Implementation of the interface which does nothing.
*
* @author <a href="mailto:[email protected]">Michael Charfadi</a>
*/
class NoOp implements IJsonResourceProcessor {

@Override
public void preDeserialization(JsonResource resource, JsonObject jsonObject) {
// Do nothing
}

@Override
public void postSerialization(JsonResource resource, JsonObject jsonObject) {
// Do nothing
}

}
}

/**
* Associate an ID to the {@link EObject}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.sirius.emfjson.resource.JsonResource;
import org.eclipse.sirius.emfjson.resource.JsonResource.IEObjectHandler;
import org.eclipse.sirius.emfjson.resource.JsonResource.IJsonResourceProcessor;
import org.eclipse.sirius.emfjson.resource.JsonResource.URIHandler;
import org.eclipse.sirius.emfjson.resource.PackageNotFoundException;

Expand Down Expand Up @@ -134,6 +135,8 @@ public class GsonEObjectDeserializer implements JsonDeserializer<List<EObject>>
*/
private IEObjectHandler eObjectHandler;

private IJsonResourceProcessor jsonResourceProcessor;

/**
* The constructor.
*
Expand Down Expand Up @@ -175,6 +178,10 @@ public GsonEObjectDeserializer(Resource resource, Map<?, ?> options) {
} else {
this.extendedMetaData = (ExtendedMetaData) this.options.get(JsonResource.OPTION_EXTENDED_META_DATA);
}
this.jsonResourceProcessor = (IJsonResourceProcessor) this.options.get(JsonResource.OPTION_JSON_RESSOURCE_PROCESSOR);
if (this.jsonResourceProcessor == null) {
this.jsonResourceProcessor = new IJsonResourceProcessor.NoOp();
}
if (this.extendedMetaData != null) {
this.helper.setExtendedMetaData(this.extendedMetaData);
}
Expand Down Expand Up @@ -245,6 +252,8 @@ public List<EObject> deserialize(JsonElement jsonElement, Type type, JsonDeseria
}
}

this.jsonResourceProcessor.preDeserialization(this.resource, jsonRoot);

// json content
this.deserializeContent(jsonRoot);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.IJsonResourceProcessor;
import org.eclipse.sirius.emfjson.resource.JsonResource.ISerializationListener;
import org.eclipse.sirius.emfjson.resource.JsonResource.ResourceEntityHandler;
import org.eclipse.sirius.emfjson.resource.exception.DanglingHREFException;
Expand Down Expand Up @@ -130,6 +131,10 @@ public class GsonEObjectSerializer implements JsonSerializer<List<EObject>> {

private ISerializationListener serializationListener;

private IJsonResourceProcessor jsonResourceProcessor;

private Resource resource;

/**
* The constructor.
*
Expand All @@ -141,7 +146,7 @@ public class GsonEObjectSerializer implements JsonSerializer<List<EObject>> {
public GsonEObjectSerializer(Resource resource, Map<?, ?> options) {
super();
Map<?, ?> serializedOptions = options;

this.resource = resource;
this.resourceEntityHandler = (ResourceEntityHandler) serializedOptions.get(JsonResource.OPTION_RESOURCE_ENTITY_HANDLER);
if (this.resourceEntityHandler instanceof JsonResource.URIHandler && !serializedOptions.containsKey(JsonResource.OPTION_URI_HANDLER)) {
Map<Object, Object> newOptions = new LinkedHashMap<Object, Object>(serializedOptions);
Expand Down Expand Up @@ -174,6 +179,10 @@ public GsonEObjectSerializer(Resource resource, Map<?, ?> options) {
if (this.serializationListener == null) {
this.serializationListener = new ISerializationListener.NoOp();
}
this.jsonResourceProcessor = (IJsonResourceProcessor) serializedOptions.get(JsonResource.OPTION_JSON_RESSOURCE_PROCESSOR);
if (this.jsonResourceProcessor == null) {
this.jsonResourceProcessor = new IJsonResourceProcessor.NoOp();
}

this.declareSchemaLocation = Boolean.TRUE.equals(options.get(JsonResource.OPTION_SCHEMA_LOCATION));

Expand Down Expand Up @@ -202,6 +211,9 @@ public JsonElement serialize(List<EObject> eObjects, Type type, JsonSerializatio
JsonObject jsonObject = new JsonObject();
jsonObject.add(IGsonConstants.JSON, jsonHeader);
jsonObject.add(IGsonConstants.NS, nsHeader);

this.jsonResourceProcessor.postSerialization((JsonResource) this.resource, jsonObject);

if (schemaLocationHeader != null) {
jsonObject.add(IGsonConstants.SCHEMA_LOCATION, schemaLocationHeader);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annota
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
Expand All @@ -33,6 +34,7 @@ org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
org.eclipse.jdt.core.compiler.problem.fallthroughCase=error
Expand Down Expand Up @@ -89,6 +91,7 @@ org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=igno
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
Expand Down Expand Up @@ -120,7 +123,8 @@ org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.compiler.release=disabled
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns=false
org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines=2147483647
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/*******************************************************************************
* Copyright (c) 2024 Obeo.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.sirius.emfjson.tests.internal.ressource.processor;

import com.google.common.io.CharStreams;
import com.google.gson.JsonObject;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.sirius.emfjson.resource.JsonResource;
import org.eclipse.sirius.emfjson.resource.JsonResourceFactoryImpl;
import org.junit.Assert;
import org.junit.Test;

/**
* Tests class for JsonResourceProcessor.
*
* @author <a href="mailto:[email protected]">Michael Charfadi</a>
*/
public class JsonResourceProcessorTests {
/**
* LF string.
*/
protected static final String LF = "\n"; //$NON-NLS-1$

/**
* CR LF string.
*/
protected static final String CRLF = "\r\n"; //$NON-NLS-1$

/**
* The path of the folder containing the models used during the tests of this class.
*/
private static final String ROOT_PATH = "/unit/resource/processor/"; //$NON-NLS-1$

/**
* The name of the JSON file used during the tests of this class.
*/
private static final String FILE_NAME = "EmptyResourceWithAddedField.json"; //$NON-NLS-1$

/**
* Serializations options.
*/
protected Map<Object, Object> saveOptions = new HashMap<Object, Object>();

/**
* DeSerializations options.
*/
protected Map<Object, Object> loadOptions = new HashMap<Object, Object>();

@Test
public void testPreDeserialization() {
ResourceSet resourceSet = new ResourceSetImpl();
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(JsonResourceFactoryImpl.EXTENSION, new JsonResourceFactoryImpl());

Resource resource = resourceSet.createResource(URI.createURI("inmemory.json")); //$NON-NLS-1$

ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
this.saveOptions.put(JsonResource.OPTION_ENCODING, JsonResource.ENCODING_UTF_8);
this.saveOptions.put(JsonResource.OPTION_PRETTY_PRINTING_INDENT, JsonResource.INDENT_2_SPACES);
this.saveOptions.put(JsonResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);

JsonResource.IJsonResourceProcessor jsonResourceProcessor = new JsonResource.IJsonResourceProcessor.NoOp() {
@Override
public void postSerialization(JsonResource resource, JsonObject jsonObject) {
jsonObject.addProperty("version", "versionNumber"); //$NON-NLS-1$ //$NON-NLS-2$
}
};

this.saveOptions.put(JsonResource.OPTION_JSON_RESSOURCE_PROCESSOR, jsonResourceProcessor);

resource.save(outputStream, this.saveOptions);

String json = new String(outputStream.toByteArray(), Charset.forName("utf-8")); //$NON-NLS-1$
String expectedResult = this.readResource(FILE_NAME);

Assert.assertEquals(expectedResult.replaceAll(CRLF, LF), json.replaceAll(CRLF, LF));
} catch (IOException e) {
Assert.fail(e.getMessage());
} finally {
try {
outputStream.close();
} catch (IOException e) {
Assert.fail(e.getMessage());
}
}
}

@Test
public void testPostSerialization() {
final URL fileURL = this.getClass().getResource(ROOT_PATH + FILE_NAME);

Resource resource = null;
InputStream inputStream = null;
try {
inputStream = fileURL.openStream();
final URI uri = URI.createURI(fileURL.toString());
ResourceSet resourceSet = new ResourceSetImpl();

JsonResourceFactoryImpl jsonResourceFactory = new JsonResourceFactoryImpl();
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put(JsonResourceFactoryImpl.EXTENSION, jsonResourceFactory);
resource = resourceSet.createResource(uri);

JsonResource.IJsonResourceProcessor jsonResourceProcessor = new JsonResource.IJsonResourceProcessor.NoOp() {
@Override
public void preDeserialization(JsonResource resource, JsonObject jsonObject) {
String versionValue = jsonObject.get("version").getAsString(); //$NON-NLS-1$
Assert.assertEquals(versionValue, "versionNumber"); //$NON-NLS-1$
}
};

this.loadOptions.put(JsonResource.OPTION_JSON_RESSOURCE_PROCESSOR, jsonResourceProcessor);

resource.load(inputStream, this.loadOptions);
} catch (IOException e) {
Assert.fail(e.getMessage());
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
Assert.fail(e.getMessage());
}
}
}
}

/**
* Returns the String value of the file represents by the given filename.
*
* @param jsonResourceName
* the file name to read
* @return the String value of the file
*/
protected String readResource(String jsonResourceName) {
URL jsonResourceUrl = this.getClass().getResource(ROOT_PATH + jsonResourceName);
InputStream inputStream = null;
InputStreamReader reader = null;
String expectedResult = ""; //$NON-NLS-1$
try {
inputStream = jsonResourceUrl.openStream();
reader = new InputStreamReader(inputStream, Charset.forName("utf-8")); //$NON-NLS-1$
expectedResult = CharStreams.toString(reader);
} catch (IOException e) {
Assert.fail(e.getMessage());
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
Assert.fail(e.getMessage());
}
}
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
Assert.fail(e.getMessage());
}
}
}
return expectedResult;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"json": {
"version": "1.0",
"encoding": "utf-8"
},
"ns": {},
"version": "versionNumber",
"content": []
}

0 comments on commit 92bd112

Please sign in to comment.