@ulb-darmstadt/shacl-form 1.7.3 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -3
- package/dist/config.d.ts +4 -5
- package/dist/constants.d.ts +15 -12
- package/dist/constraints.d.ts +5 -4
- package/dist/exports.d.ts +2 -1
- package/dist/form-bootstrap.d.ts +1 -1
- package/dist/form-bootstrap.js +361 -2
- package/dist/form-default.d.ts +1 -1
- package/dist/form-default.js +350 -2
- package/dist/form-material.d.ts +1 -1
- package/dist/form-material.js +670 -2
- package/dist/form.d.ts +3 -2
- package/dist/node-template.d.ts +17 -0
- package/dist/node.d.ts +5 -1
- package/dist/plugins/leaflet.d.ts +2 -4
- package/dist/plugins/leaflet.js +720 -2
- package/dist/plugins/mapbox.d.ts +2 -2
- package/dist/plugins/mapbox.js +2764 -2
- package/dist/property-template.d.ts +2 -1
- package/dist/property.d.ts +6 -2
- package/dist/theme.d.ts +2 -2
- package/dist/themes/default.d.ts +3 -3
- package/dist/themes/material.d.ts +2 -3
- package/package.json +26 -14
- package/src/config.ts +11 -10
- package/src/constants.ts +4 -1
- package/src/constraints.ts +75 -31
- package/src/exports.ts +2 -1
- package/src/form.ts +32 -17
- package/src/group.ts +1 -1
- package/src/loader.ts +12 -13
- package/src/node-template.ts +82 -0
- package/src/node.ts +88 -63
- package/src/plugins/leaflet.ts +2 -2
- package/src/plugins/mapbox.ts +4 -4
- package/src/property-template.ts +19 -8
- package/src/property.ts +168 -63
- package/src/serialize.ts +14 -1
- package/src/styles.css +8 -10
- package/src/theme.ts +5 -5
- package/src/themes/bootstrap.ts +1 -1
- package/src/themes/default.css +2 -2
- package/src/themes/default.ts +12 -3
- package/src/themes/material.ts +12 -3
- package/src/util.ts +12 -14
- package/dist/form-bootstrap.js.LICENSE.txt +0 -69
- package/dist/form-default.js.LICENSE.txt +0 -69
- package/dist/form-material.js.LICENSE.txt +0 -69
- package/dist/plugins/file-upload.js +0 -1
- package/dist/plugins/fixed-list.js +0 -1
- package/dist/plugins/leaflet.js.LICENSE.txt +0 -4
- package/dist/plugins/mapbox.js.LICENSE.txt +0 -10
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { BlankNode, NamedNode, Quad } from "n3"
|
|
2
|
+
import { Config } from "./config"
|
|
3
|
+
import { OWL_PREDICATE_IMPORTS, PREFIX_SHACL } from "./constants";
|
|
4
|
+
import { Term } from "@rdfjs/types";
|
|
5
|
+
|
|
6
|
+
const mappers: Record<string, (template: ShaclNodeTemplate, term: Term) => void> = {
|
|
7
|
+
[`${PREFIX_SHACL}property`]: (template, term) => { template.properties.push(term as (BlankNode | NamedNode)) },
|
|
8
|
+
[`${PREFIX_SHACL}and`]: (template, term) => { template.shaclAnd = term.value },
|
|
9
|
+
[`${PREFIX_SHACL}node`]: (template, term) => { template.node = term as NamedNode },
|
|
10
|
+
[`${PREFIX_SHACL}targetClass`]: (template, term) => { template.targetClass = term as NamedNode },
|
|
11
|
+
[`${PREFIX_SHACL}or`]: (template, term) => {
|
|
12
|
+
const list = template.config.lists[term.value]
|
|
13
|
+
if (list?.length) {
|
|
14
|
+
template.shaclOr = list
|
|
15
|
+
} else {
|
|
16
|
+
console.error('list for sh:or not found:', term.value, 'existing lists:', template.config.lists)
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
[`${PREFIX_SHACL}xone`]: (template, term) => {
|
|
20
|
+
const list = template.config.lists[term.value]
|
|
21
|
+
if (list?.length) {
|
|
22
|
+
template.shaclXone = list
|
|
23
|
+
} else {
|
|
24
|
+
console.error('list for sh:xone not found:', term.value, 'existing lists:', template.config.lists)
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
[OWL_PREDICATE_IMPORTS.id]: (template, term) => { template.owlImports.push(term as NamedNode) }
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class ShaclNodeTemplate {
|
|
31
|
+
properties: (NamedNode | BlankNode)[] = []
|
|
32
|
+
node: NamedNode | undefined
|
|
33
|
+
shaclAnd: string | undefined
|
|
34
|
+
shaclOr: Term[] | undefined
|
|
35
|
+
shaclXone: Term[] | undefined
|
|
36
|
+
targetClass: NamedNode | undefined
|
|
37
|
+
|
|
38
|
+
owlImports: NamedNode[] = []
|
|
39
|
+
config: Config
|
|
40
|
+
extendedShapes: NamedNode[] = []
|
|
41
|
+
|
|
42
|
+
constructor(quads: Quad[], config: Config) {
|
|
43
|
+
this.config = config
|
|
44
|
+
this.merge(quads)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
merge(quads: Quad[]): ShaclNodeTemplate {
|
|
48
|
+
for (const quad of quads) {
|
|
49
|
+
mappers[quad.predicate.id]?.call(this, this, quad.object)
|
|
50
|
+
}
|
|
51
|
+
// resolve extended shapes
|
|
52
|
+
if (this.node || this.shaclAnd) {
|
|
53
|
+
if (this.node) {
|
|
54
|
+
this.extendedShapes.push(this.node)
|
|
55
|
+
}
|
|
56
|
+
if (this.shaclAnd) {
|
|
57
|
+
const list = this.config.lists[this.shaclAnd]
|
|
58
|
+
if (list?.length) {
|
|
59
|
+
for (const node of list) {
|
|
60
|
+
this.extendedShapes.push(node as NamedNode)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return this
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
clone(): ShaclNodeTemplate {
|
|
69
|
+
const copy = Object.assign({}, this)
|
|
70
|
+
// arrays are not cloned but referenced, so create them manually
|
|
71
|
+
copy.owlImports = [ ...this.owlImports ]
|
|
72
|
+
if (this.shaclOr) {
|
|
73
|
+
copy.shaclOr = [ ...this.shaclOr ]
|
|
74
|
+
}
|
|
75
|
+
if (this.shaclXone) {
|
|
76
|
+
copy.shaclXone = [ ...this.shaclXone ]
|
|
77
|
+
}
|
|
78
|
+
copy.merge = this.merge.bind(copy)
|
|
79
|
+
copy.clone = this.clone.bind(copy)
|
|
80
|
+
return copy
|
|
81
|
+
}
|
|
82
|
+
}
|
package/src/node.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { BlankNode, DataFactory, NamedNode, Store } from 'n3'
|
|
2
2
|
import { Term } from '@rdfjs/types'
|
|
3
|
-
import { PREFIX_SHACL, RDF_PREDICATE_TYPE, OWL_PREDICATE_IMPORTS } from './constants'
|
|
3
|
+
import { PREFIX_SHACL, RDF_PREDICATE_TYPE, OWL_PREDICATE_IMPORTS, SHACL_PREDICATE_PROPERTY } from './constants'
|
|
4
4
|
import { ShaclProperty } from './property'
|
|
5
5
|
import { createShaclGroup } from './group'
|
|
6
6
|
import { v4 as uuidv4 } from 'uuid'
|
|
7
|
-
import { createShaclOrConstraint } from './constraints'
|
|
7
|
+
import { createShaclOrConstraint, resolveShaclOrConstraintOnNode } from './constraints'
|
|
8
8
|
import { Config } from './config'
|
|
9
9
|
|
|
10
10
|
export class ShaclNode extends HTMLElement {
|
|
@@ -14,24 +14,26 @@ export class ShaclNode extends HTMLElement {
|
|
|
14
14
|
targetClass: NamedNode | undefined
|
|
15
15
|
owlImports: NamedNode[] = []
|
|
16
16
|
config: Config
|
|
17
|
+
linked: boolean
|
|
17
18
|
|
|
18
|
-
constructor(shaclSubject: NamedNode, config: Config, valueSubject: NamedNode | BlankNode | undefined, parent?: ShaclNode, nodeKind?: NamedNode, label?: string) {
|
|
19
|
+
constructor(shaclSubject: NamedNode, config: Config, valueSubject: NamedNode | BlankNode | undefined, parent?: ShaclNode, nodeKind?: NamedNode, label?: string, linked?: boolean) {
|
|
19
20
|
super()
|
|
20
21
|
|
|
21
22
|
this.parent = parent
|
|
22
23
|
this.config = config
|
|
23
24
|
this.shaclSubject = shaclSubject
|
|
25
|
+
this.linked = linked || false
|
|
24
26
|
let nodeId: NamedNode | BlankNode | undefined = valueSubject
|
|
25
27
|
if (!nodeId) {
|
|
26
28
|
// if no value subject given, create new node id with a type depending on own nodeKind or given parent property nodeKind
|
|
27
29
|
if (!nodeKind) {
|
|
28
|
-
const spec = config.
|
|
30
|
+
const spec = config.store.getObjects(shaclSubject, `${PREFIX_SHACL}nodeKind`, null)
|
|
29
31
|
if (spec.length) {
|
|
30
32
|
nodeKind = spec[0] as NamedNode
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
// if nodeKind is not set, but a value namespace is configured or if nodeKind is sh:IRI, then create a NamedNode
|
|
34
|
-
if ((nodeKind === undefined && config.attributes.valuesNamespace) || nodeKind?.
|
|
36
|
+
if ((nodeKind === undefined && config.attributes.valuesNamespace) || nodeKind?.value === `${PREFIX_SHACL}IRI`) {
|
|
35
37
|
// no requirements on node type, so create a NamedNode and use configured value namespace
|
|
36
38
|
nodeId = DataFactory.namedNode(config.attributes.valuesNamespace + uuidv4())
|
|
37
39
|
} else {
|
|
@@ -45,17 +47,19 @@ export class ShaclNode extends HTMLElement {
|
|
|
45
47
|
const id = JSON.stringify([shaclSubject, valueSubject])
|
|
46
48
|
if (valueSubject && config.renderedNodes.has(id)) {
|
|
47
49
|
// node/value pair is already rendered in the form, so just display a reference
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
50
|
+
label = label || "Link"
|
|
51
|
+
const labelElem = document.createElement('label')
|
|
52
|
+
labelElem.innerText = label
|
|
53
|
+
labelElem.classList.add('linked')
|
|
54
|
+
this.appendChild(labelElem)
|
|
55
|
+
|
|
53
56
|
const anchor = document.createElement('a')
|
|
54
|
-
|
|
57
|
+
let refId = (valueSubject.termType === 'BlankNode') ? '_:' + valueSubject.value : valueSubject.value
|
|
58
|
+
anchor.innerText = refId
|
|
55
59
|
anchor.classList.add('ref-link')
|
|
56
60
|
anchor.onclick = () => {
|
|
57
61
|
// if anchor is clicked, scroll referenced shacl node into view
|
|
58
|
-
this.config.form.querySelector(`shacl-node[data-node-id='${
|
|
62
|
+
this.config.form.querySelector(`shacl-node[data-node-id='${refId}']`)?.scrollIntoView()
|
|
59
63
|
}
|
|
60
64
|
this.appendChild(anchor)
|
|
61
65
|
this.style.flexDirection = 'row'
|
|
@@ -64,9 +68,6 @@ export class ShaclNode extends HTMLElement {
|
|
|
64
68
|
config.renderedNodes.add(id)
|
|
65
69
|
}
|
|
66
70
|
this.dataset.nodeId = this.nodeId.id
|
|
67
|
-
const quads = config.shapesGraph.getQuads(shaclSubject, null, null, null)
|
|
68
|
-
let list: Term[] | undefined
|
|
69
|
-
|
|
70
71
|
if (this.config.attributes.showNodeIds !== null) {
|
|
71
72
|
const div = document.createElement('div')
|
|
72
73
|
div.innerText = `id: ${this.nodeId.id}`
|
|
@@ -74,39 +75,19 @@ export class ShaclNode extends HTMLElement {
|
|
|
74
75
|
this.appendChild(div)
|
|
75
76
|
}
|
|
76
77
|
|
|
77
|
-
|
|
78
|
+
// first initialize owl:imports, this is needed before adding properties to properly resolve class instances etc.
|
|
79
|
+
for (const owlImport of config.store.getQuads(shaclSubject, OWL_PREDICATE_IMPORTS, null, null)) {
|
|
80
|
+
this.owlImports.push(owlImport.object as NamedNode)
|
|
81
|
+
}
|
|
82
|
+
// now parse other node quads
|
|
83
|
+
for (const quad of config.store.getQuads(shaclSubject, null, null, null)) {
|
|
78
84
|
switch (quad.predicate.id) {
|
|
79
|
-
case
|
|
80
|
-
|
|
81
|
-
// check if property belongs to a group
|
|
82
|
-
const groupRef = config.shapesGraph.getQuads(quad.object as Term, `${PREFIX_SHACL}group`, null, null)
|
|
83
|
-
if (groupRef.length > 0) {
|
|
84
|
-
const groupSubject = groupRef[0].object.value
|
|
85
|
-
if (config.groups.indexOf(groupSubject) > -1) {
|
|
86
|
-
// check if group element already exists, otherwise create it
|
|
87
|
-
let group = this.querySelector(`:scope > .shacl-group[data-subject='${groupSubject}']`) as HTMLElement
|
|
88
|
-
if (!group) {
|
|
89
|
-
group = createShaclGroup(groupSubject, config)
|
|
90
|
-
this.appendChild(group)
|
|
91
|
-
}
|
|
92
|
-
parentElement = group
|
|
93
|
-
} else {
|
|
94
|
-
console.warn('ignoring unknown group reference', groupRef[0], 'existing groups:', config.groups)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// delay creating/appending the property until we finished parsing the node.
|
|
98
|
-
// This is needed to have possible owlImports parsed before creating the property.
|
|
99
|
-
setTimeout(() => {
|
|
100
|
-
const property = new ShaclProperty(quad.object as NamedNode | BlankNode, this, config, valueSubject)
|
|
101
|
-
// do not add empty properties (i.e. properties with no instances). This can be the case e.g. in viewer mode when there is no data for the respective property.
|
|
102
|
-
if (property.childElementCount > 0) {
|
|
103
|
-
parentElement.appendChild(property)
|
|
104
|
-
}
|
|
105
|
-
})
|
|
85
|
+
case SHACL_PREDICATE_PROPERTY.id:
|
|
86
|
+
this.addPropertyInstance(quad.object, config, valueSubject)
|
|
106
87
|
break;
|
|
107
88
|
case `${PREFIX_SHACL}and`:
|
|
108
89
|
// inheritance via sh:and
|
|
109
|
-
list = config.lists[quad.object.value]
|
|
90
|
+
const list = config.lists[quad.object.value]
|
|
110
91
|
if (list?.length) {
|
|
111
92
|
for (const shape of list) {
|
|
112
93
|
this.prepend(new ShaclNode(shape as NamedNode, config, valueSubject, this))
|
|
@@ -123,17 +104,11 @@ export class ShaclNode extends HTMLElement {
|
|
|
123
104
|
case `${PREFIX_SHACL}targetClass`:
|
|
124
105
|
this.targetClass = quad.object as NamedNode
|
|
125
106
|
break;
|
|
126
|
-
case OWL_PREDICATE_IMPORTS.id:
|
|
127
|
-
this.owlImports.push(quad.object as NamedNode)
|
|
128
|
-
break;
|
|
129
107
|
case `${PREFIX_SHACL}or`:
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
else {
|
|
135
|
-
console.error('list not found:', quad.object.value, 'existing lists:', config.lists)
|
|
136
|
-
}
|
|
108
|
+
this.tryResolve(quad.object, valueSubject, config)
|
|
109
|
+
break;
|
|
110
|
+
case `${PREFIX_SHACL}xone`:
|
|
111
|
+
this.tryResolve(quad.object, valueSubject, config)
|
|
137
112
|
break;
|
|
138
113
|
}
|
|
139
114
|
}
|
|
@@ -150,18 +125,68 @@ export class ShaclNode extends HTMLElement {
|
|
|
150
125
|
if (!subject) {
|
|
151
126
|
subject = this.nodeId
|
|
152
127
|
}
|
|
153
|
-
|
|
154
|
-
|
|
128
|
+
// output triples only if node is not a link
|
|
129
|
+
if (!this.linked) {
|
|
130
|
+
for (const shape of this.querySelectorAll(':scope > shacl-node, :scope > .shacl-group > shacl-node, :scope > shacl-property, :scope > .shacl-group > shacl-property')) {
|
|
131
|
+
(shape as ShaclNode | ShaclProperty).toRDF(graph, subject)
|
|
132
|
+
}
|
|
133
|
+
if (this.targetClass) {
|
|
134
|
+
graph.addQuad(subject, RDF_PREDICATE_TYPE, this.targetClass, this.config.valuesGraphId)
|
|
135
|
+
}
|
|
136
|
+
// if this is the root shacl node, check if we should add one of the rdf:type or dcterms:conformsTo predicates
|
|
137
|
+
if (this.config.attributes.generateNodeShapeReference && !this.parent) {
|
|
138
|
+
graph.addQuad(subject, DataFactory.namedNode(this.config.attributes.generateNodeShapeReference), this.shaclSubject, this.config.valuesGraphId)
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return subject
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
addPropertyInstance(shaclSubject: Term, config: Config, valueSubject: NamedNode | BlankNode | undefined) {
|
|
145
|
+
let parentElement: HTMLElement = this
|
|
146
|
+
// check if property belongs to a group
|
|
147
|
+
const groupRef = config.store.getQuads(shaclSubject as Term, `${PREFIX_SHACL}group`, null, null)
|
|
148
|
+
if (groupRef.length > 0) {
|
|
149
|
+
const groupSubject = groupRef[0].object.value
|
|
150
|
+
if (config.groups.indexOf(groupSubject) > -1) {
|
|
151
|
+
// check if group element already exists, otherwise create it
|
|
152
|
+
let group = this.querySelector(`:scope > .shacl-group[data-subject='${groupSubject}']`) as HTMLElement
|
|
153
|
+
if (!group) {
|
|
154
|
+
group = createShaclGroup(groupSubject, config)
|
|
155
|
+
this.appendChild(group)
|
|
156
|
+
}
|
|
157
|
+
parentElement = group
|
|
158
|
+
} else {
|
|
159
|
+
console.warn('ignoring unknown group reference', groupRef[0], 'existing groups:', config.groups)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const property = new ShaclProperty(shaclSubject as NamedNode | BlankNode, this, config, valueSubject)
|
|
163
|
+
// do not add empty properties (i.e. properties with no instances). This can be the case e.g. in viewer mode when there is no data for the respective property.
|
|
164
|
+
if (property.childElementCount > 0) {
|
|
165
|
+
parentElement.appendChild(property)
|
|
155
166
|
}
|
|
156
|
-
|
|
157
|
-
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
tryResolve(subject: Term, valueSubject: NamedNode | BlankNode | undefined, config: Config) {
|
|
170
|
+
const list = config.lists[subject.value]
|
|
171
|
+
if (list?.length) {
|
|
172
|
+
let resolved = false
|
|
173
|
+
if (valueSubject) {
|
|
174
|
+
const resolvedPropertySubjects = resolveShaclOrConstraintOnNode(list, valueSubject, config)
|
|
175
|
+
if (resolvedPropertySubjects.length) {
|
|
176
|
+
for (const propertySubject of resolvedPropertySubjects) {
|
|
177
|
+
this.addPropertyInstance(propertySubject, config, valueSubject)
|
|
178
|
+
}
|
|
179
|
+
resolved = true
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (!resolved) {
|
|
183
|
+
this.appendChild(createShaclOrConstraint(list, this, config))
|
|
184
|
+
}
|
|
158
185
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
graph.addQuad(subject, DataFactory.namedNode(this.config.attributes.generateNodeShapeReference), this.shaclSubject, this.config.valuesGraph)
|
|
186
|
+
else {
|
|
187
|
+
console.error('list for sh:or/sh:xone not found:', subject, 'existing lists:', config.lists)
|
|
162
188
|
}
|
|
163
|
-
return subject
|
|
164
189
|
}
|
|
165
190
|
}
|
|
166
191
|
|
|
167
|
-
window.customElements.define('shacl-node', ShaclNode)
|
|
192
|
+
window.customElements.define('shacl-node', ShaclNode)
|
package/src/plugins/leaflet.ts
CHANGED
|
@@ -136,12 +136,12 @@ export class LeafletPlugin extends Plugin {
|
|
|
136
136
|
document.body.style.position = 'fixed'
|
|
137
137
|
dialog.showModal()
|
|
138
138
|
}
|
|
139
|
-
const instance = fieldFactory(template, value || null)
|
|
139
|
+
const instance = fieldFactory(template, value || null, true)
|
|
140
140
|
instance.appendChild(button)
|
|
141
141
|
return instance
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
createViewer(
|
|
144
|
+
createViewer(_: ShaclPropertyTemplate, value: Term): HTMLElement {
|
|
145
145
|
const container = document.createElement('div')
|
|
146
146
|
const geometry = wktToGeometry(value.value)
|
|
147
147
|
if (geometry?.coordinates?.length) {
|
package/src/plugins/mapbox.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { ShaclPropertyTemplate } from '../property-template'
|
|
|
4
4
|
import { Editor, fieldFactory } from '../theme'
|
|
5
5
|
import { Map, NavigationControl, FullscreenControl, LngLatBounds, LngLatLike } from 'mapbox-gl'
|
|
6
6
|
import MapboxDraw from '@mapbox/mapbox-gl-draw'
|
|
7
|
-
import mapboxGlCss from 'mapbox-gl/dist/mapbox-gl.css'
|
|
8
|
-
import mapboxGlDrawCss from '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css'
|
|
7
|
+
import mapboxGlCss from 'mapbox-gl/dist/mapbox-gl.css?raw'
|
|
8
|
+
import mapboxGlDrawCss from '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css?raw'
|
|
9
9
|
import { Geometry, geometryToWkt, wktToGeometry } from './map-util'
|
|
10
10
|
|
|
11
11
|
const css = `
|
|
@@ -106,12 +106,12 @@ export class MapboxPlugin extends Plugin {
|
|
|
106
106
|
document.body.style.position = 'fixed'
|
|
107
107
|
dialog.showModal()
|
|
108
108
|
}
|
|
109
|
-
const instance = fieldFactory(template, value || null)
|
|
109
|
+
const instance = fieldFactory(template, value || null, true)
|
|
110
110
|
instance.appendChild(button)
|
|
111
111
|
return instance
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
createViewer(
|
|
114
|
+
createViewer(_: ShaclPropertyTemplate, value: Term): HTMLElement {
|
|
115
115
|
const container = document.createElement('div')
|
|
116
116
|
const geometry = wktToGeometry(value.value)
|
|
117
117
|
if (geometry?.coordinates?.length) {
|
package/src/property-template.ts
CHANGED
|
@@ -34,11 +34,11 @@ const mappers: Record<string, (template: ShaclPropertyTemplate, term: Term) => v
|
|
|
34
34
|
[`${PREFIX_SHACL}qualifiedValueShape`]: (template, term) => { template.qualifiedValueShape = term },
|
|
35
35
|
[`${PREFIX_SHACL}qualifiedMinCount`]: (template, term) => { template.minCount = parseInt(term.value) },
|
|
36
36
|
[`${PREFIX_SHACL}qualifiedMaxCount`]: (template, term) => { template.maxCount = parseInt(term.value) },
|
|
37
|
-
[OWL_PREDICATE_IMPORTS.id]:
|
|
38
|
-
[SHACL_PREDICATE_CLASS.id]:
|
|
37
|
+
[OWL_PREDICATE_IMPORTS.id]: (template, term) => { template.owlImports.push(term as NamedNode) },
|
|
38
|
+
[SHACL_PREDICATE_CLASS.id]: (template, term) => {
|
|
39
39
|
template.class = term as NamedNode
|
|
40
40
|
// try to find node shape that has requested target class
|
|
41
|
-
const nodeShapes = template.config.
|
|
41
|
+
const nodeShapes = template.config.store.getSubjects(SHACL_PREDICATE_TARGET_CLASS, term, null)
|
|
42
42
|
if (nodeShapes.length > 0) {
|
|
43
43
|
template.node = nodeShapes[0] as NamedNode
|
|
44
44
|
}
|
|
@@ -48,12 +48,20 @@ const mappers: Record<string, (template: ShaclPropertyTemplate, term: Term) => v
|
|
|
48
48
|
if (list?.length) {
|
|
49
49
|
template.shaclOr = list
|
|
50
50
|
} else {
|
|
51
|
-
console.error('list not found:', term.value, 'existing lists:', template.config.lists)
|
|
51
|
+
console.error('list for sh:or not found:', term.value, 'existing lists:', template.config.lists)
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
[`${PREFIX_SHACL}xone`]: (template, term) => {
|
|
55
|
+
const list = template.config.lists[term.value]
|
|
56
|
+
if (list?.length) {
|
|
57
|
+
template.shaclXone = list
|
|
58
|
+
} else {
|
|
59
|
+
console.error('list for sh:xone not found:', term.value, 'existing lists:', template.config.lists)
|
|
52
60
|
}
|
|
53
61
|
}
|
|
54
62
|
}
|
|
55
63
|
|
|
56
|
-
export class ShaclPropertyTemplate
|
|
64
|
+
export class ShaclPropertyTemplate {
|
|
57
65
|
parent: ShaclNode
|
|
58
66
|
label = ''
|
|
59
67
|
name: Literal | undefined
|
|
@@ -79,6 +87,7 @@ export class ShaclPropertyTemplate {
|
|
|
79
87
|
shaclAnd: string | undefined
|
|
80
88
|
shaclIn: string | undefined
|
|
81
89
|
shaclOr: Term[] | undefined
|
|
90
|
+
shaclXone: Term[] | undefined
|
|
82
91
|
languageIn: Term[] | undefined
|
|
83
92
|
datatype: NamedNode | undefined
|
|
84
93
|
hasValue: Term | undefined
|
|
@@ -86,14 +95,14 @@ export class ShaclPropertyTemplate {
|
|
|
86
95
|
owlImports: NamedNode[] = []
|
|
87
96
|
|
|
88
97
|
config: Config
|
|
89
|
-
extendedShapes: NamedNode[]
|
|
98
|
+
extendedShapes: NamedNode[] = []
|
|
90
99
|
|
|
91
100
|
constructor(quads: Quad[], parent: ShaclNode, config: Config) {
|
|
92
101
|
this.parent = parent
|
|
93
102
|
this.config = config
|
|
94
103
|
this.merge(quads)
|
|
95
104
|
if (this.qualifiedValueShape) {
|
|
96
|
-
this.merge(config.
|
|
105
|
+
this.merge(config.store.getQuads(this.qualifiedValueShape, null, null, null))
|
|
97
106
|
}
|
|
98
107
|
}
|
|
99
108
|
|
|
@@ -108,7 +117,6 @@ export class ShaclPropertyTemplate {
|
|
|
108
117
|
}
|
|
109
118
|
// resolve extended shapes
|
|
110
119
|
if (this.node || this.shaclAnd) {
|
|
111
|
-
this.extendedShapes = []
|
|
112
120
|
if (this.node) {
|
|
113
121
|
this.extendedShapes.push(this.node)
|
|
114
122
|
}
|
|
@@ -134,6 +142,9 @@ export class ShaclPropertyTemplate {
|
|
|
134
142
|
if (this.shaclOr) {
|
|
135
143
|
copy.shaclOr = [ ...this.shaclOr ]
|
|
136
144
|
}
|
|
145
|
+
if (this.shaclXone) {
|
|
146
|
+
copy.shaclXone = [ ...this.shaclXone ]
|
|
147
|
+
}
|
|
137
148
|
copy.merge = this.merge.bind(copy)
|
|
138
149
|
copy.clone = this.clone.bind(copy)
|
|
139
150
|
return copy
|