@ulb-darmstadt/shacl-form 1.6.1 → 1.6.3

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/src/util.ts ADDED
@@ -0,0 +1,116 @@
1
+ import { NamedNode, Prefixes, Quad, Store } from 'n3'
2
+ import { OWL_OBJECT_NAMED_INDIVIDUAL, PREFIX_RDFS, PREFIX_SHACL, PREFIX_SKOS, RDFS_PREDICATE_SUBCLASS_OF, RDF_PREDICATE_TYPE, SHAPES_GRAPH, SKOS_PREDICATE_BROADER } from './constants'
3
+ import { Term } from '@rdfjs/types'
4
+ import { InputListEntry } from './theme'
5
+ import { ShaclPropertyTemplate } from './property-template'
6
+ import { ShaclNode } from './node'
7
+
8
+ export function findObjectValueByPredicate(quads: Quad[], predicate: string, prefix: string = PREFIX_SHACL, languages?: string[]): string {
9
+ let result = ''
10
+ const object = findObjectByPredicate(quads, predicate, prefix, languages)
11
+ if (object) {
12
+ result = object.value
13
+ }
14
+ return result
15
+ }
16
+
17
+ export function findObjectByPredicate(quads: Quad[], predicate: string, prefix: string = PREFIX_SHACL, languages?: string[]): Term | undefined {
18
+ let candidate: Term | undefined
19
+ const prefixedPredicate = prefix + predicate
20
+
21
+ if (languages?.length) {
22
+ for (const language of languages) {
23
+ for (const quad of quads) {
24
+ if (quad.predicate.value === prefixedPredicate) {
25
+ if (quad.object.id.endsWith(`@${language}`)) {
26
+ return quad.object
27
+ }
28
+ else if (quad.object.id.indexOf('@') < 0) {
29
+ candidate = quad.object
30
+ } else if (!candidate) {
31
+ candidate = quad.object
32
+ }
33
+ }
34
+ }
35
+ }
36
+ } else {
37
+ for (const quad of quads) {
38
+ if (quad.predicate.value === prefixedPredicate) {
39
+ return quad.object
40
+ }
41
+ }
42
+ }
43
+ return candidate
44
+ }
45
+
46
+ export function focusFirstInputElement(context: HTMLElement) {
47
+ (context.querySelector('input,select,textarea') as HTMLElement)?.focus()
48
+ }
49
+
50
+ export function findLabel(quads: Quad[], languages: string[]): string {
51
+ let label = findObjectValueByPredicate(quads, 'prefLabel', PREFIX_SKOS, languages)
52
+ if (label) {
53
+ return label
54
+ }
55
+ return findObjectValueByPredicate(quads, 'label', PREFIX_RDFS, languages)
56
+ }
57
+
58
+ export function createInputListEntries(subjects: Term[], shapesGraph: Store, languages: string[], indent?: number): InputListEntry[] {
59
+ const entries: InputListEntry[] = []
60
+ for (const subject of subjects) {
61
+ entries.push({ value: subject, label: findLabel(shapesGraph.getQuads(subject, null, null, null), languages), indent: indent })
62
+ }
63
+ return entries
64
+ }
65
+
66
+ export function removePrefixes(id: string, prefixes: Prefixes): string {
67
+ for (const key in prefixes) {
68
+ // need to ignore type check. 'prefix' is a string and not a NamedNode<string> (seems to be a bug in n3 typings)
69
+ // @ts-ignore
70
+ id = id.replace(prefixes[key], '')
71
+ }
72
+ return id
73
+ }
74
+
75
+ function findClassInstancesFromOwlImports(clazz: NamedNode, context: ShaclNode | ShaclPropertyTemplate, shapesGraph: Store, instances: Term[], alreadyCheckedImports = new Set<string>()) {
76
+ for (const owlImport of context.owlImports) {
77
+ if (!alreadyCheckedImports.has(owlImport.id)) {
78
+ alreadyCheckedImports.add(owlImport.id)
79
+ instances.push(...shapesGraph.getSubjects(RDF_PREDICATE_TYPE, clazz, owlImport))
80
+ }
81
+ }
82
+ if (context.parent) {
83
+ findClassInstancesFromOwlImports(clazz, context.parent, shapesGraph, instances, alreadyCheckedImports)
84
+ }
85
+ }
86
+
87
+ export function findInstancesOf(clazz: NamedNode, template: ShaclPropertyTemplate, indent = 0): InputListEntry[] {
88
+ // find instances in the shapes graph
89
+ const instances: Term[] = template.config.shapesGraph.getSubjects(RDF_PREDICATE_TYPE, clazz, SHAPES_GRAPH)
90
+ // find instances in the data graph
91
+ instances.push(...template.config.dataGraph.getSubjects(RDF_PREDICATE_TYPE, clazz, null))
92
+ // find instances in imported taxonomies
93
+ findClassInstancesFromOwlImports(clazz, template, template.config.shapesGraph, instances)
94
+
95
+ const entries = createInputListEntries(instances, template.config.shapesGraph, template.config.languages, indent)
96
+ for (const subClass of template.config.shapesGraph.getSubjects(RDFS_PREDICATE_SUBCLASS_OF, clazz, null)) {
97
+ entries.push(...findInstancesOf(subClass as NamedNode, template, indent + 1))
98
+ }
99
+ if (template.config.shapesGraph.getQuads(clazz, RDF_PREDICATE_TYPE, OWL_OBJECT_NAMED_INDIVIDUAL, null).length > 0) {
100
+ entries.push(...createInputListEntries([ clazz ], template.config.shapesGraph, template.config.languages, indent))
101
+ for (const subClass of template.config.shapesGraph.getSubjects(SKOS_PREDICATE_BROADER, clazz, null)) {
102
+ entries.push(...findInstancesOf(subClass as NamedNode, template, indent + 1))
103
+ }
104
+ }
105
+ return entries
106
+ }
107
+
108
+ export function isURL(input: string): boolean {
109
+ let url: URL
110
+ try {
111
+ url = new URL(input)
112
+ } catch (_) {
113
+ return false
114
+ }
115
+ return url.protocol === 'http:' || url.protocol === 'https:'
116
+ }