@@ -2,7 +2,13 @@ import type sparqljs from 'sparqljs'
2
2
import { match , P } from 'ts-pattern'
3
3
import type { DataFactory , DefaultGraph , Quad_Predicate } from '@rdfjs/types' // eslint-disable-line camelcase
4
4
5
- type Term = sparqljs . IriTerm | sparqljs . BlankTerm | sparqljs . LiteralTerm | sparqljs . Variable | sparqljs . QuadTerm | DefaultGraph
5
+ type Term =
6
+ sparqljs . IriTerm
7
+ | sparqljs . BlankTerm
8
+ | sparqljs . LiteralTerm
9
+ | sparqljs . Variable
10
+ | sparqljs . QuadTerm
11
+ | DefaultGraph
6
12
7
13
export interface Processor {
8
14
process < Q extends sparqljs . SparqlQuery > ( query : Q ) : Q
@@ -136,11 +142,18 @@ export default abstract class ProcessorImpl<F extends DataFactory = DataFactory>
136
142
137
143
processQuads ( quads : sparqljs . Quads ) : sparqljs . Quads {
138
144
return match ( quads )
139
- . with ( { type : 'bgp' } , bgp => this . processBgp ( bgp ) )
145
+ . with ( { type : 'bgp' } , bgp => {
146
+ const processed = this . processBgp ( bgp )
147
+ const maybeBgp = Array . isArray ( processed ) ? processed [ 0 ] : processed
148
+ if ( maybeBgp . type !== 'bgp' ) {
149
+ throw new Error ( 'Quads must be transformed to a single bgp pattern' )
150
+ }
151
+ return maybeBgp
152
+ } )
140
153
. with ( { type : 'graph' } , ( graph ) : sparqljs . GraphQuads => ( {
141
154
type : 'graph' ,
142
155
name : this . processTerm ( graph . name ) ,
143
- triples : graph . triples . map ( triple => this . processTriple ( triple ) ) ,
156
+ triples : graph . triples . map < sparqljs . Triple > ( triple => this . processTripleStrict ( triple ) ) ,
144
157
} ) )
145
158
. exhaustive ( )
146
159
}
@@ -174,15 +187,15 @@ export default abstract class ProcessorImpl<F extends DataFactory = DataFactory>
174
187
return {
175
188
queryType : 'CONSTRUCT' ,
176
189
...this . processBaseQuery ( query ) ,
177
- template : query . template ?. map ( triple => this . processTriple ( triple ) ) ,
190
+ template : query . template ?. map ( triple => this . processTripleStrict ( triple ) ) ,
178
191
}
179
192
}
180
193
181
194
processPatterns ( where : sparqljs . Pattern [ ] ) : sparqljs . Pattern [ ] {
182
- return where . map ( ( pattern ) => this . processPattern ( pattern ) ) . filter ( Boolean )
195
+ return where . flatMap ( ( pattern ) => this . processPattern ( pattern ) ) . filter ( Boolean )
183
196
}
184
197
185
- processPattern ( pattern : sparqljs . Pattern ) : sparqljs . Pattern {
198
+ processPattern ( pattern : sparqljs . Pattern ) : sparqljs . Pattern | sparqljs . Pattern [ ] {
186
199
return match ( pattern )
187
200
. with ( { type : 'bgp' } , ( bgp ) => this . processBgp ( bgp ) )
188
201
. with ( { type : 'values' } , values => this . processValues ( values ) )
@@ -291,14 +304,31 @@ export default abstract class ProcessorImpl<F extends DataFactory = DataFactory>
291
304
return this . factory . literal ( literal . value , langOrDt )
292
305
}
293
306
294
- processBgp ( bgp : sparqljs . BgpPattern ) : sparqljs . BgpPattern {
295
- return {
296
- ...bgp ,
297
- triples : bgp . triples . map ( triple => this . processTriple ( triple ) ) ,
298
- }
307
+ processBgp ( { triples } : sparqljs . BgpPattern ) : sparqljs . Pattern | sparqljs . Pattern [ ] {
308
+ let currentBgp : sparqljs . BgpPattern | undefined
309
+
310
+ return triples . reduce ( ( patterns : sparqljs . Pattern [ ] , triple ) => {
311
+ const result = this . processTriple ( triple )
312
+ const processedTriples = Array . isArray ( result ) ? result : [ result ]
313
+
314
+ return processedTriples . reduce ( ( patterns : sparqljs . Pattern [ ] , processedTriple ) => {
315
+ if ( 'subject' in processedTriple ) {
316
+ if ( ! currentBgp ) {
317
+ currentBgp = { type : 'bgp' , triples : [ processedTriple ] }
318
+ return [ ...patterns , currentBgp ]
319
+ }
320
+
321
+ currentBgp . triples . push ( processedTriple )
322
+ return patterns
323
+ }
324
+
325
+ currentBgp = undefined
326
+ return [ ...patterns , processedTriple ]
327
+ } , patterns )
328
+ } , [ ] )
299
329
}
300
330
301
- processTriple ( triple : sparqljs . Triple ) : sparqljs . Triple {
331
+ processTriple ( triple : sparqljs . Triple ) : sparqljs . Triple | sparqljs . Triple [ ] | sparqljs . Pattern | sparqljs . Pattern [ ] {
302
332
return {
303
333
subject : this . processTerm ( triple . subject ) ,
304
334
predicate : match ( triple . predicate )
@@ -308,6 +338,14 @@ export default abstract class ProcessorImpl<F extends DataFactory = DataFactory>
308
338
}
309
339
}
310
340
341
+ private processTripleStrict ( triple : sparqljs . Triple ) : sparqljs . Triple {
342
+ const processed = this . processTriple ( triple )
343
+ if ( ! ( 'subject' in processed ) ) {
344
+ throw new Error ( 'Triple must be transformed to another triple' )
345
+ }
346
+ return processed
347
+ }
348
+
311
349
processPropertyPath ( path : sparqljs . PropertyPath ) : sparqljs . PropertyPath {
312
350
if ( path . pathType === '!' ) {
313
351
return this . processNegatedPropertySet ( path )
@@ -337,7 +375,7 @@ export default abstract class ProcessorImpl<F extends DataFactory = DataFactory>
337
375
}
338
376
}
339
377
340
- processGroup ( group : sparqljs . GroupPattern ) : sparqljs . Pattern {
378
+ processGroup ( group : sparqljs . GroupPattern ) : sparqljs . Pattern {
341
379
return {
342
380
...group ,
343
381
patterns : this . processPatterns ( group . patterns ) ,
@@ -373,7 +411,7 @@ export default abstract class ProcessorImpl<F extends DataFactory = DataFactory>
373
411
. with ( { type : 'functionCall' } , functionCall => this . processFunctionCall ( functionCall ) )
374
412
. with ( { type : 'aggregate' } , aggregate => aggregate )
375
413
. when ( Array . isArray , ( tuple : sparqljs . Expression [ ] ) => tuple . map ( expression => this . processExpression ( expression ) ) )
376
- . with ( { equals : P . instanceOf ( Function ) } , term => this . processTerm ( term ) )
414
+ . with ( { termType : P . string } , term => this . processTerm ( term ) )
377
415
. exhaustive ( )
378
416
}
379
417
@@ -392,7 +430,16 @@ export default abstract class ProcessorImpl<F extends DataFactory = DataFactory>
392
430
...operation ,
393
431
args : operation . args . map ( arg =>
394
432
match ( arg )
395
- . when ( isPattern , operation => this . processPattern ( operation ) )
433
+ . when ( isPattern , operation => {
434
+ const processed = this . processPattern ( operation )
435
+ if ( Array . isArray ( processed ) ) {
436
+ if ( processed . length > 1 ) {
437
+ throw new Error ( 'Operation argument cannot be transformed to an array' )
438
+ }
439
+ return processed [ 0 ]
440
+ }
441
+ return processed
442
+ } )
396
443
. otherwise ( ( ) => this . processExpression ( arg as sparqljs . Expression ) ) ,
397
444
) ,
398
445
}
0 commit comments