Skip to content

Commit

Permalink
fix: construct with multiple targe class
Browse files Browse the repository at this point in the history
  • Loading branch information
tpluscode committed Nov 1, 2022
1 parent 5e13eb8 commit 5792668
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/smooth-cobras-behave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hydrofoil/shape-to-query": patch
---

`FILTER` was added to the `CONSTRUCT` clause when there were multiple `sh:targetClass`
11 changes: 8 additions & 3 deletions packages/shape-to-query/lib/shapeToPatterns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface Options {
focusNode?: NamedNode
objectVariablePrefix?: string
strict?: boolean
patternsOnly?: true
}

type PropertyShapeOptions = Pick<Options, 'objectVariablePrefix' | 'strict'>
Expand All @@ -23,11 +24,11 @@ export function shapeToPatterns(shape: GraphPointer, options: Options): SparqlTe
prefix: options.subjectVariable || 'resource',
})

return sparql`${targetClass(shape, focusNode)}
return sparql`${targetClass(shape, focusNode, options.patternsOnly)}
${propertyShapes(shape, focusNode, options)}`
}

function targetClass(shape: GraphPointer, focusNode: PrefixedVariable) {
function targetClass(shape: GraphPointer, focusNode: PrefixedVariable, patternsOnly?: boolean) {
const targetClass = shape.out(sh.targetClass).terms
if (!targetClass.length) {
return ''
Expand All @@ -38,6 +39,10 @@ function targetClass(shape: GraphPointer, focusNode: PrefixedVariable) {
}

const typeVar = focusNode.extend('targetClass')
if (patternsOnly) {
return sparql`${focusNode()} a ${typeVar()} .`
}

return sparql`
${focusNode()} a ${typeVar()} .
FILTER ( ${typeVar()} ${IN(...targetClass)} )
Expand All @@ -55,7 +60,7 @@ function propertyShapes(shape: GraphPointer, focusNode: PrefixedVariable, option
return sparql`${focusNode()} ${propShape.out(sh.path).term} ${variable()} .`
})

if (options.strict === false) {
if (propertyPatterns.length > 1 && options.strict === false) {
return propertyPatterns.reduce((union, next, index) => {
if (index === 0) {
return sparql`{ ${next} }`
Expand Down
2 changes: 1 addition & 1 deletion packages/shape-to-query/lib/shapeToQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { shapeToPatterns, Options } from './shapeToPatterns'

export function construct(shape: GraphPointer, options: Omit<Options, 'strict'> = {}) {
return CONSTRUCT`
${shapeToPatterns(shape, { ...options, strict: true })}
${shapeToPatterns(shape, { ...options, strict: true, patternsOnly: true })}
`.WHERE`
${shapeToPatterns(shape, { ...options, strict: false })}
`
Expand Down
28 changes: 28 additions & 0 deletions packages/shape-to-query/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,34 @@ describe('@hydrofoil/shape-to-query', () => {
{ ${ex.John} ${foaf.lastName} ?resource_1 . }
}`)
})

it('generates a query with multiple target types', async () => {
// given
const shape = await parse`
<>
a ${sh.NodeShape} ;
${sh.targetClass} ${foaf.Person}, ${schema.Person} ;
${sh.property}
[
${sh.path} ${foaf.name} ;
] ;
.
`

// when
const focusNode = ex.John
const query = construct(shape, { focusNode }).build()

// then
expect(query).to.be.a.query(sparql`CONSTRUCT {
${ex.John} a ?resource_targetClass .
${ex.John} ${foaf.name} ?resource_0 .
} WHERE {
${ex.John} a ?resource_targetClass .
FILTER ( ?resource_targetClass IN (${foaf.Person}, ${schema.Person}) )
${ex.John} ${foaf.name} ?resource_0 .
}`)
})
})
})
})

0 comments on commit 5792668

Please sign in to comment.