From cdbf855e2154679327913e5ed63685f3ee7711c6 Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Mon, 30 Oct 2023 17:10:59 +0100 Subject: [PATCH] [28] Add support for changing attributes type Bug: https://github.com/eclipse-sirius/sirius-emf-json/issues/28 --- .../utils/GsonEObjectDeserializer.java | 29 +++++-- .../sirius/emfjson/utils/JsonHelper.java | 12 ++- .../tests/internal/AbstractEMFJsonTests.java | 5 ++ .../unit/load/JsonHelperDataLoadTests.java | 75 +++++++++++++++++++ .../TestChangeAttributeTypeMono.json | 21 ++++++ .../TestChangeAttributeTypeMono.xmi | 8 ++ .../TestChangeAttributeTypeMulti.json | 25 +++++++ .../TestChangeAttributeTypeMulti.xmi | 11 +++ 8 files changed, 179 insertions(+), 7 deletions(-) create mode 100644 tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/unit/load/JsonHelperDataLoadTests.java create mode 100644 tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMono.json create mode 100644 tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMono.xmi create mode 100644 tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMulti.json create mode 100644 tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMulti.xmi diff --git a/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/utils/GsonEObjectDeserializer.java b/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/utils/GsonEObjectDeserializer.java index 8c89047..15c64e1 100644 --- a/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/utils/GsonEObjectDeserializer.java +++ b/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/utils/GsonEObjectDeserializer.java @@ -911,22 +911,41 @@ private void deserializeEAttribute(EAttribute eAttribute, JsonElement jsonElemen EDataType dataType = eAttribute.getEAttributeType(); if (!eAttribute.isMany()) { String newValue = this.getAsFlexibleString(jsonElement); - Object value = EcoreUtil.createFromString(dataType, newValue); + Object value = this.tryCreateDataTypeFromString(dataType, newValue); this.helper.setValue(eObject, eAttribute, value); } else { JsonArray asJsonArray = this.getAsFlexibleArray(jsonElement); Object eGet = this.helper.getValue(eObject, eAttribute); if (eGet instanceof Collection) { for (JsonElement jElement : asJsonArray) { - Object value = EcoreUtil.createFromString(dataType, jElement.getAsString()); - @SuppressWarnings("unchecked") - Collection collection = (Collection) eGet; - collection.add(value); + Object value = this.tryCreateDataTypeFromString(dataType, jElement.getAsString()); + this.helper.setValue(eObject, eAttribute, value); } } } } + /** + * Try to create a {@link EDataType} instance from a serialized form of the value. If the serialization is not + * compatible with the given EDataType, returns the serialized form of the value unchanged. + * + * @param dataType + * The {@link EDataType} to instantiate + * @param serializedValue + * The serialized form of the value + * @return A new EDataType instance or the given serializedValue if the EDataType could not be instantiated from the + * serializedValue. + */ + private Object tryCreateDataTypeFromString(EDataType dataType, String serializedValue) { + Object value; + try { + value = EcoreUtil.createFromString(dataType, serializedValue); + } catch (IllegalArgumentException e) { + value = serializedValue; + } + return value; + } + /** * Read a JSON element as a string. If the element is a non-empty array, unwrap it and consider the first element * inside instead of trying to convert the array into a string. diff --git a/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/utils/JsonHelper.java b/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/utils/JsonHelper.java index 27c5125..2b5751d 100644 --- a/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/utils/JsonHelper.java +++ b/bundles/org.eclipse.sirius.emfjson/src/main/java/org/eclipse/sirius/emfjson/utils/JsonHelper.java @@ -14,6 +14,7 @@ package org.eclipse.sirius.emfjson.utils; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -581,7 +582,8 @@ public EClassifier getType(EFactory eFactory, String typeName) { } /** - * Sets the value of the feature for the given object. + * Sets the value of the feature for the given object. If the feature is multivalued, add the value to the + * collection of values already set. * * @param object * the given object @@ -591,7 +593,13 @@ public EClassifier getType(EFactory eFactory, String typeName) { * the value to set */ public void setValue(EObject object, EStructuralFeature feature, Object value) { - object.eSet(feature, value); + if (feature.isMany()) { + @SuppressWarnings("unchecked") + Collection collection = (Collection) object.eGet(feature); + collection.add(value); + } else { + object.eSet(feature, value); + } } /** 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 955b19c..5ff1c6a 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 @@ -43,6 +43,7 @@ import org.eclipse.sirius.emfjson.resource.JsonResource; import org.eclipse.sirius.emfjson.resource.JsonResourceFactoryImpl; import org.eclipse.sirius.emfjson.resource.JsonResourceImpl; +import org.eclipse.sirius.emfjson.utils.JsonHelper; import org.junit.Assert; /** @@ -276,6 +277,10 @@ public Resource createResource(URI uriValue) { resource = resourceSet.createResource(uri); String extension = resource.getURI().fileExtension(); if (extension.equals(JsonResourceFactoryImpl.EXTENSION)) { + if (this.options.get(JsonResource.OPTION_CUSTOM_HELPER) instanceof JsonHelper) { + JsonHelper jsonHelper = (JsonHelper) this.options.get(JsonResource.OPTION_CUSTOM_HELPER); + jsonHelper.setResource(resource); + } resource.load(inputStream, this.options); } else { resource.load(inputStream, Collections.EMPTY_MAP); diff --git a/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/unit/load/JsonHelperDataLoadTests.java b/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/unit/load/JsonHelperDataLoadTests.java new file mode 100644 index 0000000..cc32c35 --- /dev/null +++ b/tests/org.eclipse.sirius.emfjson.tests/src/main/java/org/eclipse/sirius/emfjson/tests/internal/unit/load/JsonHelperDataLoadTests.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2023 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.unit.load; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.sirius.emfjson.resource.JsonResource; +import org.eclipse.sirius.emfjson.tests.internal.AbstractEMFJsonTests; +import org.eclipse.sirius.emfjson.utils.JsonHelper; +import org.junit.Test; + +/** + * Tests loading with ExtendedMetaData. + */ +public class JsonHelperDataLoadTests extends AbstractEMFJsonTests { + + /** + * {@inheritDoc} + * + * @see org.eclipse.sirius.emfjson.tests.internal.AbstractEMFJsonTests#getRootPath() + */ + @Override + protected String getRootPath() { + return "/unit/attributes/extendedmetadata/"; //$NON-NLS-1$ + } + + /** + * Change the type of a monovalued EAttribute. + */ + @Test + public void testChangeAttributeTypeMono() { + JsonHelper jsonHelper = new JsonHelper() { + @Override + public void setValue(EObject object, EStructuralFeature feature, Object value) { + Object newValue = value; + if ("NodeSingleValueAttribute".equals(feature.getEContainingClass().getName()) && "singleIntAttribute".equals(feature.getName())) { //$NON-NLS-1$ //$NON-NLS-2$ + newValue = new Integer(((String) value).length()); + } + super.setValue(object, feature, newValue); + } + }; + + this.options.put(JsonResource.OPTION_CUSTOM_HELPER, jsonHelper); + this.testLoad("TestChangeAttributeTypeMono.xmi"); //$NON-NLS-1$ + } + + /** + * Change the type of a monovalued EAttribute. + */ + @Test + public void testChangeAttributeTypeMulti() { + JsonHelper jsonHelper = new JsonHelper() { + @Override + public void setValue(EObject object, EStructuralFeature feature, Object value) { + Object newValue = value; + if ("NodeMultiValuedAttribute".equals(feature.getEContainingClass().getName()) && "multiIntAttribute".equals(feature.getName())) { //$NON-NLS-1$ //$NON-NLS-2$ + newValue = new Integer(((String) value).length()); + } + super.setValue(object, feature, newValue); + } + }; + + this.options.put(JsonResource.OPTION_CUSTOM_HELPER, jsonHelper); + this.testLoad("TestChangeAttributeTypeMulti.xmi"); //$NON-NLS-1$ + } + +} diff --git a/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMono.json b/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMono.json new file mode 100644 index 0000000..888b286 --- /dev/null +++ b/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMono.json @@ -0,0 +1,21 @@ +{ + "json": { + "version": "1.0", + "encoding": "utf-8" + }, + "ns": { + "emfjson": "http://obeo.fr/emfjson", + "nodes": "http://www.obeo.fr/EMFJson" + }, + "schemaLocation": { + "http://www.obeo.fr/EMFJson": "../../../nodes.ecore" + }, + "content": [ + { + "eClass": "nodes:NodeSingleValueAttribute", + "data": { + "singleIntAttribute": "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + } + } + ] +} \ No newline at end of file diff --git a/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMono.xmi b/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMono.xmi new file mode 100644 index 0000000..1f500ef --- /dev/null +++ b/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMono.xmi @@ -0,0 +1,8 @@ + + diff --git a/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMulti.json b/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMulti.json new file mode 100644 index 0000000..3c949f6 --- /dev/null +++ b/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMulti.json @@ -0,0 +1,25 @@ +{ + "json": { + "version": "1.0", + "encoding": "utf-8" + }, + "ns": { + "emfjson": "http://obeo.fr/emfjson", + "nodes": "http://www.obeo.fr/EMFJson" + }, + "schemaLocation": { + "http://www.obeo.fr/EMFJson": "../../../nodes.ecore" + }, + "content": [ + { + "eClass": "nodes:NodeMultiValuedAttribute", + "data": { + "multiIntAttribute": [ + "ABC", + "ABCDEF", + "ABCDEFGHI" + ] + } + } + ] +} \ No newline at end of file diff --git a/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMulti.xmi b/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMulti.xmi new file mode 100644 index 0000000..c2e01d4 --- /dev/null +++ b/tests/org.eclipse.sirius.emfjson.tests/src/main/resources/unit/attributes/extendedmetadata/TestChangeAttributeTypeMulti.xmi @@ -0,0 +1,11 @@ + + + 3 + 6 + 9 +