Skip to content
This repository was archived by the owner on Jun 26, 2021. It is now read-only.

Commit 2209aa3

Browse files
committed
Fix issue introduced by #54
For contained objects, the type present in the JSON object was not taken into account, the type use to create the object was the direct type of the reference, which is not correct if the object's type is a sub type of the reference type.
1 parent 4882106 commit 2209aa3

6 files changed

Lines changed: 204 additions & 42 deletions

File tree

emfjson-jackson/src/main/java/org/emfjson/jackson/databind/deser/EObjectDeserializer.java

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -48,32 +48,31 @@ public EObjectDeserializer(ResourceSet resourceSet, JacksonOptions options) {
4848
}
4949

5050
@Override
51-
public EObject deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
52-
final EClass root = findRoot(ctxt);
53-
54-
EObject current = null;
55-
if (root != null) {
56-
current = EcoreUtil.create(root);
57-
}
51+
public boolean isCachable() {
52+
return true;
53+
}
5854

59-
return doDeserialize(jp, current, ctxt);
55+
@Override
56+
public EObject deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
57+
return doDeserialize(jp, findRoot(ctxt), ctxt);
6058
}
6159

6260
public EObject deserialize(JsonParser jp, DeserializationContext ctxt, EReference containment) throws IOException {
63-
EObject current = null;
61+
EClass defaultType = null;
6462

6563
if (containment != null) {
66-
final EClass defaultType = containment.getEReferenceType();
64+
defaultType = containment.getEReferenceType();
6765

68-
if (!defaultType.isAbstract()) {
69-
current = EcoreUtil.create(defaultType);
66+
if (defaultType.isAbstract()) {
67+
defaultType = null;
7068
}
7169
}
7270

73-
return doDeserialize(jp, current, ctxt);
71+
return doDeserialize(jp, defaultType, ctxt);
7472
}
7573

76-
protected EObject doDeserialize(JsonParser jp, EObject current, DeserializationContext ctxt) throws IOException {
74+
protected EObject doDeserialize(JsonParser jp, EClass defaultType, DeserializationContext ctxt) throws IOException {
75+
EObject current = null;
7776
final Resource resource = (Resource) ctxt.getAttribute("resource");
7877
final ReferenceEntries entries = (ReferenceEntries) ctxt.getAttribute("entries");
7978
final TokenBuffer buffer = new TokenBuffer(jp);
@@ -102,15 +101,17 @@ protected EObject doDeserialize(JsonParser jp, EObject current, Deserialization
102101
}
103102
}
104103

105-
postDeserialize(buffer, current, ctxt);
106-
buffer.close();
107-
108-
return current;
104+
return postDeserialize(buffer, current, defaultType, ctxt);
109105
}
110106

111-
protected void postDeserialize(TokenBuffer buffer, EObject object, DeserializationContext ctxt) throws IOException {
112-
if (object == null)
113-
return;
107+
protected EObject postDeserialize(TokenBuffer buffer, EObject object, EClass defaultType, DeserializationContext ctxt) throws IOException {
108+
if (object == null && defaultType == null) {
109+
return null;
110+
}
111+
112+
if (object == null) {
113+
object = EcoreUtil.create(defaultType);
114+
}
114115

115116
final Resource resource = (Resource) ctxt.getAttribute("resource");
116117
final ReferenceEntries entries = (ReferenceEntries) ctxt.getAttribute("entries");
@@ -121,6 +122,9 @@ protected void postDeserialize(TokenBuffer buffer, EObject object, Deserializati
121122
}
122123

123124
bufferedParser.close();
125+
buffer.close();
126+
127+
return object;
124128
}
125129

126130
private EClass findRoot(DeserializationContext ctxt) {

emfjson-jackson/src/main/java/org/emfjson/jackson/databind/deser/ResourceDeserializer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ public ResourceDeserializer(ResourceSet resourceSet, JacksonOptions options) {
3535
this.options = options;
3636
}
3737

38+
@Override
39+
public boolean isCachable() {
40+
return true;
41+
}
42+
3843
@Override
3944
public Resource deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
4045
final Resource resource = getResource(ctxt);

emfjson-jackson/src/test/java/org/emfjson/jackson/junit/support/TestSupport.java

Lines changed: 121 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,17 @@
1111
*/
1212
package org.emfjson.jackson.junit.support;
1313

14+
import com.fasterxml.jackson.databind.ObjectMapper;
1415
import org.eclipse.emf.common.util.URI;
1516
import org.eclipse.emf.ecore.*;
1617
import org.eclipse.emf.ecore.resource.Resource;
1718
import org.eclipse.emf.ecore.resource.ResourceSet;
1819
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
1920
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
20-
import org.junit.Before;
21-
2221
import org.emfjson.jackson.junit.model.ModelPackage;
2322
import org.emfjson.jackson.module.EMFModule;
2423
import org.emfjson.jackson.resource.JsonResourceFactory;
25-
26-
import com.fasterxml.jackson.databind.ObjectMapper;
24+
import org.junit.Before;
2725

2826
import java.net.URL;
2927
import java.text.SimpleDateFormat;
@@ -68,11 +66,35 @@ protected void createDynamicModel() {
6866
p.setNsPrefix("model");
6967
p.setNsURI("http://emfjson/dynamic/model");
7068

69+
// classes a, b, c, d
70+
// a
71+
// b > a
72+
// c > b > a
73+
7174
EClass a = EcoreFactory.eINSTANCE.createEClass();
7275
a.setName("A");
7376

74-
EEnum ee = EcoreFactory.eINSTANCE.createEEnum();
75-
ee.setName("Kind");
77+
EClass b = EcoreFactory.eINSTANCE.createEClass();
78+
b.setName("B");
79+
80+
EClass c = EcoreFactory.eINSTANCE.createEClass();
81+
c.setName("C");
82+
83+
EClass d = EcoreFactory.eINSTANCE.createEClass();
84+
d.setName("D");
85+
86+
b.getESuperTypes().add(a);
87+
c.getESuperTypes().add(b);
88+
d.getESuperTypes().add(b);
89+
90+
// dataTypes
91+
//
92+
// Kind: Enum
93+
// - e1
94+
// - e2: E2
95+
96+
EEnum kind = EcoreFactory.eINSTANCE.createEEnum();
97+
kind.setName("Kind");
7698

7799
EEnumLiteral e1 = EcoreFactory.eINSTANCE.createEEnumLiteral();
78100
e1.setName("e1");
@@ -81,17 +103,102 @@ protected void createDynamicModel() {
81103
e2.setName("e2");
82104
e2.setLiteral("E2");
83105

84-
ee.getELiterals().add(e1);
85-
ee.getELiterals().add(e2);
86-
87-
EAttribute ae = EcoreFactory.eINSTANCE.createEAttribute();
88-
ae.setName("singleKind");
89-
ae.setEType(ee);
106+
kind.getELiterals().add(e1);
107+
kind.getELiterals().add(e2);
90108

91-
a.getEStructuralFeatures().add(ae);
109+
// CustomType
110+
EDataType customDataType = EcoreFactory.eINSTANCE.createEDataType();
111+
customDataType.setName("CustomType");
112+
customDataType.setSerializable(true);
92113

93114
p.getEClassifiers().add(a);
94-
p.getEClassifiers().add(ee);
115+
p.getEClassifiers().add(b);
116+
p.getEClassifiers().add(c);
117+
p.getEClassifiers().add(d);
118+
p.getEClassifiers().add(kind);
119+
p.getEClassifiers().add(customDataType);
120+
121+
// attributes
122+
//
123+
// a:
124+
// stringValue: string
125+
// intValue: int
126+
// stringValues: string[]
127+
// intValues: int[]
128+
// dateValue: date
129+
// someKind: kind
130+
// custom: CustomType
131+
132+
EAttribute stringValue = EcoreFactory.eINSTANCE.createEAttribute();
133+
stringValue.setName("stringValue");
134+
stringValue.setUnsettable(true);
135+
stringValue.setEType(EcorePackage.Literals.ESTRING);
136+
137+
EAttribute stringValues = EcoreFactory.eINSTANCE.createEAttribute();
138+
stringValues.setName("stringValues");
139+
stringValues.setUpperBound(-1);
140+
stringValues.setEType(EcorePackage.Literals.ESTRING);
141+
142+
EAttribute intValue = EcoreFactory.eINSTANCE.createEAttribute();
143+
intValue.setName("intValue");
144+
intValue.setEType(EcorePackage.Literals.EINT);
145+
146+
EAttribute intValues = EcoreFactory.eINSTANCE.createEAttribute();
147+
intValues.setName("intValues");
148+
intValues.setUpperBound(-1);
149+
intValues.setEType(EcorePackage.Literals.EINT);
150+
151+
EAttribute dateValue = EcoreFactory.eINSTANCE.createEAttribute();
152+
dateValue.setName("dateValue");
153+
dateValue.setEType(EcorePackage.Literals.EDATE);
154+
155+
EAttribute someKind = EcoreFactory.eINSTANCE.createEAttribute();
156+
someKind.setName("someKind");
157+
someKind.setEType(kind);
158+
159+
EAttribute customValue = EcoreFactory.eINSTANCE.createEAttribute();
160+
customValue.setName("customValue");
161+
customValue.setEType(customDataType);
162+
163+
a.getEStructuralFeatures().add(stringValue);
164+
a.getEStructuralFeatures().add(stringValues);
165+
a.getEStructuralFeatures().add(intValue);
166+
a.getEStructuralFeatures().add(intValues);
167+
a.getEStructuralFeatures().add(dateValue);
168+
a.getEStructuralFeatures().add(someKind);
169+
a.getEStructuralFeatures().add(customValue);
170+
171+
// references
172+
// a:
173+
// containB: B
174+
// containBs: B[]
175+
// refTo: A
176+
// refToMany: A[]
177+
178+
EReference containB = EcoreFactory.eINSTANCE.createEReference();
179+
containB.setName("containB");
180+
containB.setContainment(true);
181+
containB.setEType(b);
182+
183+
EReference containBs = EcoreFactory.eINSTANCE.createEReference();
184+
containBs.setName("containBs");
185+
containBs.setContainment(true);
186+
containBs.setUpperBound(-1);
187+
containBs.setEType(b);
188+
189+
EReference refTo = EcoreFactory.eINSTANCE.createEReference();
190+
refTo.setName("refTo");
191+
refTo.setEType(a);
192+
193+
EReference refToMany = EcoreFactory.eINSTANCE.createEReference();
194+
refToMany.setName("refTo");
195+
refToMany.setUpperBound(-1);
196+
refToMany.setEType(a);
197+
198+
a.getEStructuralFeatures().add(containB);
199+
a.getEStructuralFeatures().add(containBs);
200+
a.getEStructuralFeatures().add(refTo);
201+
a.getEStructuralFeatures().add(refToMany);
95202

96203
Resource model = resourceSet.createResource(URI.createURI("http://emfjson/dynamic/model"));
97204
model.getContents().add(p);

emfjson-jackson/src/test/java/org/emfjson/jackson/junit/tests/EnumTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public void testLoadEnumDifferentCases() throws IOException {
149149
public void testSaveDynamicEnum() {
150150
JsonNode expected = mapper.createObjectNode()
151151
.put("eClass", "http://emfjson/dynamic/model#//A")
152-
.put("singleKind", "e1");
152+
.put("someKind", "e1");
153153

154154
EClass a = (EClass) resourceSet.getEObject(URI.createURI("http://emfjson/dynamic/model#//A"), true);
155155
EObject a1 = EcoreUtil.create(a);
@@ -163,7 +163,7 @@ public void testSaveDynamicEnum() {
163163
public void testLoadDynamicEnum() throws IOException {
164164
JsonNode data = mapper.createObjectNode()
165165
.put("eClass", "http://emfjson/dynamic/model#//A")
166-
.put("singleKind", "E2");
166+
.put("someKind", "E2");
167167

168168
Resource resource = resourceSet.createResource(URI.createURI("tests/test.json"));
169169
resource.load(new ByteArrayInputStream(mapper.writeValueAsBytes(data)), options);
@@ -174,7 +174,7 @@ public void testLoadDynamicEnum() throws IOException {
174174

175175
assertEquals("A", root.eClass().getName());
176176

177-
Object literal = root.eGet(root.eClass().getEStructuralFeature("singleKind"));
177+
Object literal = root.eGet(root.eClass().getEStructuralFeature("someKind"));
178178

179179
assertTrue(literal instanceof EEnumLiteral);
180180

emfjson-jackson/src/test/java/org/emfjson/jackson/junit/tests/PolymorphicTest.java

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,18 @@
1111
*/
1212
package org.emfjson.jackson.junit.tests;
1313

14+
import com.fasterxml.jackson.databind.JsonNode;
1415
import org.eclipse.emf.common.util.URI;
16+
import org.eclipse.emf.ecore.EClass;
1517
import org.eclipse.emf.ecore.EObject;
1618
import org.eclipse.emf.ecore.resource.Resource;
17-
import org.junit.Test;
18-
1919
import org.emfjson.EMFJs;
2020
import org.emfjson.jackson.junit.model.*;
2121
import org.emfjson.jackson.junit.support.TestSupport;
22-
23-
import com.fasterxml.jackson.databind.JsonNode;
22+
import org.junit.Test;
2423

2524
import java.io.IOException;
25+
import java.util.List;
2626

2727
import static org.junit.Assert.*;
2828

@@ -105,4 +105,31 @@ public void testLoadTwoObjectsWithReferenceAndTypeInformation() throws IOExcepti
105105
assertSame(second, ref);
106106
}
107107

108+
@Test
109+
public void testContainmentWithHierarchyOfTypes() {
110+
Resource resource = resourceSet.getResource(uri("test-types-dynamic-1.json"), true);
111+
112+
assertEquals(1, resource.getContents().size());
113+
114+
EObject root = resource.getContents().get(0);
115+
116+
assertEquals("A", root.eClass().getName());
117+
118+
EClass a = root.eClass();
119+
assertTrue(root.eIsSet(a.getEStructuralFeature("containB")));
120+
assertTrue(root.eIsSet(a.getEStructuralFeature("containBs")));
121+
122+
EObject root_c1 = (EObject) root.eGet(a.getEStructuralFeature("containB"));
123+
List<EObject> root_c2 = (List<EObject>) root.eGet(a.getEStructuralFeature("containBs"));
124+
125+
assertEquals("C", root_c1.eClass().getName());
126+
assertEquals(2, root_c2.size());
127+
128+
assertEquals("C", root_c2.get(0).eClass().getName());
129+
130+
EObject c2 = root_c2.get(0);
131+
assertEquals("Hello", c2.eGet(c2.eClass().getEStructuralFeature("stringValue")));
132+
133+
assertEquals("D", root_c2.get(1).eClass().getName());
134+
}
108135
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"eClass": "http://emfjson/dynamic/model#//A",
3+
"containB": {
4+
"eClass": "http://emfjson/dynamic/model#//C"
5+
},
6+
"containBs": [
7+
{
8+
"stringValue": "Hello",
9+
"eClass": "http://emfjson/dynamic/model#//C",
10+
"containB": {
11+
"eClass": "http://emfjson/dynamic/model#//C"
12+
}
13+
},
14+
{
15+
"eClass": "http://emfjson/dynamic/model#//D",
16+
"stringValue": "Hello"
17+
}
18+
]
19+
}

0 commit comments

Comments
 (0)