public async validateRelationshipsByPath()

in source/packages/services/assetlibrary/src/types/types.full.dao.ts [632:780]


    public async validateRelationshipsByPath(templateId:string, relations:DirectionStringToArrayMap): Promise<RelationsByPath> {
        logger.debug(`types.full.dao validateRelationshipsByPath: in: templateId:${templateId}, relations:${JSON.stringify(relations)}`);

        const id = `type___${templateId.toLowerCase()}`;

        let results;
        const rels_paths_in:string[]=[];
        const rels_paths_out:string[]=[];

        const conn = super.getConnection();
        try {
            // get a handle on the type
            const traverser = conn.traversal.V(id).
                outE('current_definition').has('status','published').inV().as('def');

            // get all known allowed relationships
            traverser.select('def').bothE('relationship').fold().as('rels');

            // extrapolate the paths from the rels parameter to make our lives easier...
            if (relations && relations.in) {
                Object.keys(relations.in).forEach(rel=> {
                    relations.in[rel].forEach(path=> {
                        rels_paths_in.push(path.toLowerCase());
                    });
                });
            }
            if (relations && relations.out) {
                Object.keys(relations.out).forEach(rel=> {
                    relations.out[rel].forEach(path=> {
                        rels_paths_out.push(path.toLowerCase());
                    });
                });
            }

            // get a handle to the groups that we're trying to associate with, and project them
            let index = 1;
            const groupAliases:string[]=[];
            rels_paths_in.forEach(path=> {
                const alias = `g_in_${index}`;
                traverser.V(`group___${path.toLowerCase()}`).as(alias);
                groupAliases.push(alias);
                index++;
            });
            rels_paths_out.forEach(path=> {
                const alias = `g_out_${index}`;
                traverser.V(`group___${path.toLowerCase()}`).as(alias);
                groupAliases.push(alias);
                index++;
            });

            // we need to project all the groups, as well as details of the allowed relationships
            const projections:string[]=[];
            projections.push(...groupAliases);
            projections.push('rels');
            projections.push('rels_props');
            traverser.project(...projections);

            // return the details of all the groups to match with the above projections
            groupAliases.forEach(alias=> traverser.by(__.select(alias)));

            // also return details of the relations (the edge) along with the relations properties (its valuemap)
            traverser.by(__.select('rels'));
            traverser.by(__.select('rels').unfold().valueMap().with_(process.withOptions.tokens).fold());

            // execute the query
            logger.debug(`types.full.dao validateRelationshipsByPath: traverser: ${JSON.stringify(traverser.toString())}`);
            results = await traverser.next();
        } finally {
            await conn.close();
        }

        // parse the results
        const groupTypes_in:GroupType[]=[];
        const groupTypes_out:GroupType[]=[];
        const rels:unknown[]=[];
        const rels_props:unknown[]=[];
        const validGroups_in:string[]=[];
        const validGroups_out:string[]=[];
        const allowed_rels:AllowedRelation[]=[];
        logger.debug(`types.full.dao validateRelationshipsByPath: results: ${JSON.stringify(results)}`);

        if (results!==undefined && results.value!==null) {
            const values = JSON.parse(JSON.stringify(results.value));
            Object.keys(values).forEach(k=> {
                if (k.startsWith('g_')) {
                    // this is a group that we have found based on the provided relations data
                    const path = this.extractNameFromId( values[k].id);
                    const isIncoming = k.startsWith('g_in_');

                    if (isIncoming) {
                        validGroups_in.push(path);
                    } else {
                        validGroups_out.push(path);
                    }
                    (values[k].label.split('::') as string[]).
                        filter(l=> l!=='group' && l!=='device').
                        forEach(l=> {
                            if (isIncoming) {
                                groupTypes_in.push({path,template:l});
                            } else {
                                groupTypes_out.push({path,template:l});
                            }
                        });
                } else if (k==='rels') {
                    // this is an allowed relationship for the provided templateId
                    for(const r of values[k]) {
                        rels.push(r);
                    }
                } else if (k==='rels_props') {
                    // this is an allowed relationship (its properties) for the provided templateId
                    for(const r of values[k]) {
                        rels_props.push(r);
                    }
                }
            });
        }

        // format the allowed relations to make it easier to work with
        for(const r of rels) {
            const rel_props = rels_props.filter(rp=> rp['id']===r['id'])[0];
            allowed_rels.push({
               name:rel_props['name'],
               outType:this.extractNameFromId(r['outV']['id']),
               inType:this.extractNameFromId(r['inV']['id'])
            });
        }

        // validate that all requested group paths were found
        const invalidGroups:string[]=[];
        rels_paths_in.forEach(path=> {
            if (!validGroups_in.includes(path)) {
                invalidGroups.push(path);
            }
        });
        rels_paths_out.forEach(path=> {
            if (!validGroups_out.includes(path)) {
                invalidGroups.push(path);
            }
        });

        const response:RelationsByPath = {
            groupTypes_in,
            groupTypes_out,
            rels: allowed_rels,
            invalidGroups
        };
        logger.debug(`types.full.dao validateRelationshipsByPath: exit: ${JSON.stringify(response)}`);
        return response;
    }