Warning: session_start(): open(/var/lib/php/sessions/sess_c6j263eco3p4dcauga9fmsjipn, O_RDWR) failed: No space left on device (28) in /var/www/tb-usercake/models/config.php on line 51
Warning: session_start(): Failed to read session data: files (path: /var/lib/php/sessions) in /var/www/tb-usercake/models/config.php on line 51
sclass JsonDiff {
srecord DiffResult(O a, O b) {}
srecord GatheredKey(S key, O value) {} // key made from getListKey
sclass Removed > DiffResult { *(O *a, O *b) {} } // b missing
sclass Added > DiffResult { *(O *a, O *b) {} } // a missing
sclass DifferentType > DiffResult { *(O *a, O *b) {} }
sclass Different > DiffResult { *(O *a, O *b) {} } // same type, generally different
// paths are usually L, but IDs gathered by getListKey can also be in there
IF1 getListKey; // key field for diffing lists. argument is path
// returns null if identical
O diff(S json1, S json2) {
O o1 = jsonDecode(json1), o2 = jsonDecode(json2);
ret diff(json1, json2, new L);
}
// a, b = decoded JSON
O diff(O a, O b) {
ret diff(a, b, new L);
}
// a, b = decoded JSON
O diff(O a, O b, L path) {
if (eq(a, b)) null;
if (a == null) ret new Added(a, b);
if (b == null) ret new Removed(a, b);
if (a.getClass() != b.getClass()) ret new DifferentType(a, b);
// from here on, we know that a and b have the same type
if (a cast Map)
ret diffMaps(a, (Map) b, path);
if (a cast L)
try object diffLists(a, (L) b, path);
ret new Different(a, b);
}
O diffMaps(Map a, Map b, L path) {
ret withoutNullValues
(mapKeyAndFunction_lhm(concatAsOrderedSet(keys(a), keys(b)),
key -> {
temp tempAddToList(path, key);
ret diff(a.get(key), b/Map.get(key), path);
}));
}
O diffLists(L a, L b, L path) {
S key = callF(getListKey, path);
if (key == null) null;
Map mapA = gatherListElements(a, key, path);
if (mapA == null) null;
Map mapB = gatherListElements(b, key, path);
if (mapB == null) null;
ret diffMaps(mapA, mapB, path);
}
Map gatherListElements(L l, S key, L path) {
new LinkedHashMap mapOut;
for (O x : l) {
if (!x instanceof Map)
ret null with print("Can't get object key " + key + " of non-map (path: " + path + ")");
mapOut.put(new GatheredKey(key, x/Map.get(key)), x);
}
ret mapOut;
}
}