11
11
import org .lionweb .lioncore .java .model .impl .M3Node ;
12
12
import org .lionweb .lioncore .java .self .LionCore ;
13
13
14
+ import javax .annotation .Nullable ;
14
15
import java .util .*;
15
16
import java .util .stream .Collectors ;
16
17
@@ -58,6 +59,7 @@ public static JsonSerialization getBasicSerialization() {
58
59
59
60
private Map <String , JsonObject > nodeIdToData = new HashMap <>();
60
61
private Map <String , Node > nodeIdToNode = new HashMap <>();
62
+ private Map <String , NodeData > nodeIdToNodeData = new HashMap <>();
61
63
62
64
private JsonSerialization () {
63
65
// prevent public access
@@ -194,6 +196,19 @@ private <T extends Node> T populateProperties(T instance, JsonObject jsonObject)
194
196
return instance ;
195
197
}
196
198
199
+ private NodeData populateProperties (NodeData instance , JsonObject jsonObject ) {
200
+ if (!jsonObject .has ("properties" ) && jsonObject .get ("properties" ).isJsonObject ()) {
201
+ return instance ;
202
+ }
203
+ JsonObject properties = jsonObject .getAsJsonObject ("properties" );
204
+ for (String propertyId : properties .keySet ()) {
205
+ String serializedValue = properties .get (propertyId ).getAsString ();
206
+ instance .setPropertyValue (propertyId , serializedValue );
207
+ }
208
+
209
+ return instance ;
210
+ }
211
+
197
212
private void populateLinks (Node node , JsonObject data ) {
198
213
if (data .has ("children" )) {
199
214
JsonObject children = data .get ("children" ).getAsJsonObject ();
@@ -248,6 +263,40 @@ private void populateLinks(Node node, JsonObject data) {
248
263
}
249
264
}
250
265
266
+ private void populateLinks (NodeData node , JsonObject data ) {
267
+ if (data .has ("children" )) {
268
+ JsonObject children = data .get ("children" ).getAsJsonObject ();
269
+ for (String containmentID : children .keySet ()) {
270
+ JsonArray value = children .get (containmentID ).getAsJsonArray ();
271
+ for (JsonElement childEl : value .asList ()) {
272
+ String childId = childEl .getAsString ();
273
+ node .addChild (containmentID , childId );
274
+ }
275
+ }
276
+ }
277
+ if (data .has ("references" )) {
278
+ JsonObject references = data .get ("references" ).getAsJsonObject ();
279
+ for (String referenceID : references .keySet ()) {
280
+ JsonArray value = references .get (referenceID ).getAsJsonArray ();
281
+ for (JsonElement referredEl : value .asList ()) {
282
+ try {
283
+ JsonObject referenceObj = referredEl .getAsJsonObject ();
284
+ String referredId = getAsStringOrNull (referenceObj .get ("reference" ));
285
+ String resolveInfo = getAsStringOrNull (referenceObj .get ("resolveInfo" ));
286
+ node .addReferenceValue (referenceID , new NodeData .RawReferenceValue (referredId , resolveInfo ));
287
+ } catch (Exception e ) {
288
+ throw new RuntimeException ("Issue deserializing reference " + referenceID , e );
289
+ }
290
+ }
291
+ }
292
+ }
293
+ if (data .has ("parent" )) {
294
+ JsonElement parentValue = data .get ("parent" );
295
+ String parentNodeID = parentValue instanceof JsonNull ? null : parentValue .getAsString ();
296
+ node .setParentNodeID (parentNodeID );
297
+ }
298
+ }
299
+
251
300
private String getAsStringOrNull (JsonElement element ) {
252
301
if (element == null || element .isJsonNull ()) {
253
302
return null ;
@@ -256,7 +305,53 @@ private String getAsStringOrNull(JsonElement element) {
256
305
}
257
306
}
258
307
259
- public List <Node > unserialize (JsonElement jsonElement ) {
308
+ /**
309
+ * This will return a lower-level representation of the information stored in JSON.
310
+ * It is intended to load broken models.
311
+ *
312
+ * Possible usages: repair a broken model, extract a metamodel from the model (“model archeology”), etc.
313
+ *
314
+ * This method follows a "best-effort" approach, try to limit exception thrown and return data whenever is possible,
315
+ * in the measure that it is possible.
316
+ */
317
+ public List <NodeData > rawUnserialization (JsonElement jsonElement ) {
318
+ if (jsonElement .isJsonObject ()) {
319
+ JsonObject topLevel = jsonElement .getAsJsonObject ();
320
+ if (!topLevel .has ("nodes" )) {
321
+ return Collections .emptyList ();
322
+ }
323
+ if (topLevel .get ("nodes" ).isJsonArray ()) {
324
+ List <NodeData > nodes = topLevel .get ("nodes" ).getAsJsonArray ().asList ().stream ().map (element -> {
325
+ try {
326
+ NodeData nodeData = unserializeNodeData (element );
327
+ if (nodeData != null && nodeData .getID () != null ) {
328
+ this .nodeIdToData .put (nodeData .getID (), element .getAsJsonObject ());
329
+ this .nodeIdToNodeData .put (nodeData .getID (), nodeData );
330
+ }
331
+ return nodeData ;
332
+ } catch (Exception e ) {
333
+ throw new RuntimeException ("Issue while unserializing " + element , e );
334
+ }
335
+ }).filter (e -> e != null ).collect (Collectors .toList ());
336
+ for (Map .Entry <String , JsonObject > entry : nodeIdToData .entrySet ()) {
337
+ try {
338
+ populateLinks (nodeIdToNodeData .get (entry .getKey ()), entry .getValue ());
339
+ } catch (Exception e ) {
340
+ throw new RuntimeException ("Issue while unserializing " + entry , e );
341
+ }
342
+ }
343
+ nodeIdToData .clear ();
344
+ nodeIdToNodeData .clear ();
345
+ return nodes ;
346
+ } else {
347
+ return Collections .emptyList ();
348
+ }
349
+ } else {
350
+ return Collections .emptyList ();
351
+ }
352
+ }
353
+
354
+ public List <Node > unserializeToNode (JsonElement jsonElement ) {
260
355
if (jsonElement .isJsonObject ()) {
261
356
JsonObject topLevel = jsonElement .getAsJsonObject ();
262
357
if (!topLevel .has ("serializationFormatVersion" )) {
@@ -315,6 +410,20 @@ private Node unserializeNode(JsonElement jsonElement) {
315
410
}
316
411
}
317
412
413
+ @ Nullable
414
+ private NodeData unserializeNodeData (JsonElement jsonElement ) {
415
+ if (jsonElement .isJsonObject ()) {
416
+ JsonObject jsonObject = jsonElement .getAsJsonObject ();
417
+ String conceptID = tryToGetStringProperty (jsonObject , CONCEPT_LABEL );
418
+ String nodeID = tryToGetStringProperty (jsonObject , ID_LABEL );
419
+ NodeData nodeData = new NodeData (nodeID , conceptID );
420
+ populateProperties (nodeData , jsonObject );
421
+ return nodeData ;
422
+ } else {
423
+ return null ;
424
+ }
425
+ }
426
+
318
427
private String getStringProperty (JsonObject jsonObject , String propertyName ) {
319
428
if (!jsonObject .has (propertyName )) {
320
429
throw new IllegalArgumentException (propertyName + " property not found in " + jsonObject );
@@ -327,4 +436,17 @@ private String getStringProperty(JsonObject jsonObject, String propertyName) {
327
436
}
328
437
}
329
438
439
+ @ Nullable
440
+ private String tryToGetStringProperty (JsonObject jsonObject , String propertyName ) {
441
+ if (!jsonObject .has (propertyName )) {
442
+ return null ;
443
+ }
444
+ JsonElement value = jsonObject .get (propertyName );
445
+ if (value .isJsonPrimitive () && value .getAsJsonPrimitive ().isString ()) {
446
+ return value .getAsJsonPrimitive ().getAsString ();
447
+ } else {
448
+ return null ;
449
+ }
450
+ }
451
+
330
452
}
0 commit comments