private identifyChangedRelations()

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
        };
    }