import { DocumentNode } from "graphql" ; import { DefinitionNode } from "graphql/language" ; import * as RDF from "@rdfjs/types" ; import { Algebra , Factory , Util as AlgebraUtil } from "sparqlalgebrajs" ; import { IConvertContext } from "../IConvertContext" ; import { IConvertSettings } from "../IConvertSettings" ; import { Util } from "../Util" ; import { INodeQuadContext , NodeHandlerAdapter } from "./NodeHandlerAdapter" ; /**
 * Converts GraphQL documents to joined operations for all its definitions.
 */ export class NodeHandlerDocument extends NodeHandlerAdapter < DocumentNode > { constructor ( util , settings ) { super ( 'Document' , util , settings ) ; } public handle ( document , convertContext ) { const definitionOperations = document . definitions . map ( ( definition ) => { const subjectOutput = this . getNodeQuadContextDefinitionNode ( definition , { ... convertContext , ignoreUnknownVariables : true } ) ; const queryParseContext = { ... convertContext , graph : subjectOutput . graph || convertContext . graph , subject : subjectOutput . subject || this . util . dataFactory . blankNode ( ) , } ; let definitionOperation = this . util . handleNode ( definition , queryParseContext ) ; if ( subjectOutput && subjectOutput . auxiliaryPatterns ) { definitionOperation = this . util . joinOperations ( [ definitionOperation , this . util . operationFactory . createBgp ( subjectOutput . auxiliaryPatterns ) , ] ) ; } return definitionOperation ; } ) ; const operation = this . util . operationFactory . createProject ( definitionOperations . length === 1 ? definitionOperations [ 0 ] : this . util . operationFactory . createUnion ( definitionOperations ) , convertContext . terminalVariables ) ; return this . translateBlankNodesToVariables ( operation ) ; } param { DefinitionNode } definition param { IConvertContext } convertContext return { INodeQuadContext } public getNodeQuadContextDefinitionNode ( definition , convertContext ) { if ( definition . kind === 'OperationDefinition' ) { return this . getNodeQuadContextSelectionSet ( definition . selectionSet , definition . name ? definition . name . value : '' , convertContext ) ; } throw new Error ( `Unsupported definition: ${ definition . kind }` ) ; } param { Project } operation return { Operation } public translateBlankNodesToVariables ( operation ) { const self = this ; const blankToVariableMapping = { } ; const variablesRaw = Array . from ( operation . variables ) . reduce ( ( acc , variable ) => { acc [ variable . value ] = true ; return acc ; } , { } ) ; return AlgebraUtil . mapOperation ( operation , { path : ( op , factory ) => { return { recurse : false , result : factory . createPath ( blankToVariable ( op . subject ) , op . predicate , blankToVariable ( op . object ) , blankToVariable ( op . graph ) ) , } ; } , pattern : ( op , factory ) => { return { recurse : false , result : factory . createPattern ( blankToVariable ( op . subject ) , blankToVariable ( op . predicate ) , blankToVariable ( op . object ) , blankToVariable ( op . graph ) ) , } ; } , } ) ; function blankToVariable ( term ) { if ( term . termType === 'BlankNode' ) { let variable = blankToVariableMapping [ term . value ] ; if ( ! variable ) { variable = AlgebraUtil . createUniqueVariable ( term . value , variablesRaw , self . util . dataFactory ) ; variablesRaw [ variable . value ] = true ; blankToVariableMapping [ term . value ] = variable ; } return variable ; } return term ; } } }