in source/packages/services/assetlibrary/src/types/types.full.dao.ts [327:464]
private identifyChangedRelations(existing:TypeRelationsModel, updated:TypeRelationsModel): ChangedRelations {
// before we diff, sort the relations. this avoids reporting any unneccessary modifications where just the ordering may have changed
if (existing && existing.in) {
for (const key of Object.keys(existing.in)) {
existing.in[key]=existing.in[key].sort();
}
}
if (existing && existing.out) {
for (const key of Object.keys(existing.out)) {
existing.out[key]=existing.out[key].sort();
}
}
if (updated && updated.in) {
for (const key of Object.keys(updated.in)) {
updated.in[key]=updated.in[key].sort();
}
}
if (updated && updated.out) {
for (const key of Object.keys(updated.out)) {
updated.out[key]=updated.out[key].sort();
}
}
// perform a diff of the relations so we can determine what specifically to add and remove
const diff = jsonpatch.compare(existing, updated);
// based on the changes, build up the relation changes query
const toRemove = new TypeRelationsModel();
toRemove.in = {};
toRemove.out = {};
const toAdd = new TypeRelationsModel();
toAdd.in = {};
toAdd.out = {};
const processed4Levels:string[]=[];
diff.forEach(d=> {
const p = d.path.split('/');
if (p.length===2) { //////////////////// entire in/out
if (d.op==='remove') {
if (p[1]==='in') {
for (const key of Object.keys(existing.in)) {
toRemove.in[key] = existing['in'][key];
}
} else if (p[1]==='out') {
for (const key of Object.keys(existing.out)) {
toRemove.out[key] = existing['out'][key];
}
}
} else if (d.op==='add') {
if (p[1]==='in') {
for (const key of Object.keys(updated.in)) {
toAdd.in[key] = updated['in'][key];
}
} else if (p[1]==='out') {
for (const key of Object.keys(updated.out)) {
toAdd.out[key] = updated['out'][key];
}
}
} else {
logger.warn(`types.full.dao Unsupported diff op: ${JSON.stringify(d)}`);
}
} else if (p.length===3) { //////////////////// specific relation changed
if (d.op==='remove') {
if (p[1]==='in') {
toRemove.in[p[2]] = existing['in'][p[2]];
} else if (p[1]==='out') {
toRemove.out[p[2]] = existing['out'][p[2]];
}
} else if (d.op==='add') {
if (p[1]==='in') {
toAdd.in[p[2]] = updated['in'][p[2]];
} else if (p[1]==='out') {
toAdd.out[p[2]] = updated['out'][p[2]];
}
} else {
logger.warn(`types.full.dao Unsupported diff op: ${JSON.stringify(d)}`);
}
} else if (p.length===4) { //////////////////// a target type of a relation has changed
// the diff output isnt great to work with for array diffs, therefore calculate the diff ourselves
if (processed4Levels.indexOf(`${p[1]}/${p[2]}`)<0) {
processed4Levels.push(`${p[1]}/${p[2]}`);
const existingTypes = (p[1]==='in') ? existing['in'][p[2]] : existing['out'][p[2]];
const updatedTypes = (p[1]==='in') ? updated['in'][p[2]] : updated['out'][p[2]];
// first find removed
if (existingTypes) {
existingTypes.forEach(t=> {
if (updatedTypes.indexOf(t)<0) {
if (p[1]==='in') {
if (toRemove.in[p[2]]===undefined) {
toRemove.in[p[2]]=[];
}
toRemove.in[p[2]].push(t);
} else {
if (toRemove.out[p[2]]===undefined) {
toRemove.out[p[2]]=[];
}
toRemove.out[p[2]].push(t);
}
}
});
}
// then find added
if (updatedTypes) {
updatedTypes.forEach(t=> {
if (existingTypes.indexOf(t)<0) {
if (p[1]==='in') {
if (toAdd.in[p[2]]===undefined) {
toAdd.in[p[2]]=[];
}
toAdd.in[p[2]].push(t);
} else {
if (toAdd.out[p[2]]===undefined) {
toAdd.out[p[2]]=[];
}
toAdd.out[p[2]].push(t);
}
}
});
}
}
} else {
logger.warn(`types.full.dao Unsupported diff op: ${JSON.stringify(d)}`);
}
});
return {
add: toAdd,
remove: toRemove
};
}