@shaclmate/shacl-ast 3.0.4 → 4.0.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.
@@ -1,2 +1,312 @@
1
- export {};
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import TermMap from "@rdfjs/term-map";
8
+ import TermSet from "@rdfjs/term-set";
9
+ import { owl, sh } from "@tpluscode/rdf-ns-builders";
10
+ import { Either, Left } from "purify-ts";
11
+ import { Resource, ResourceSet } from "rdfjs-resource";
12
+ import { Memoize } from "typescript-memoize";
13
+ import * as generated from "./generated.js";
14
+ import { NodeShape } from "./NodeShape.js";
15
+ import { Ontology } from "./Ontology.js";
16
+ import { PropertyGroup } from "./PropertyGroup.js";
17
+ import { PropertyShape } from "./PropertyShape.js";
18
+ export class ShapesGraph {
19
+ nodeShapesByIdentifier;
20
+ ontologiesByIdentifier;
21
+ propertyGroupsByIdentifier;
22
+ propertyShapesByIdentifier;
23
+ constructor(parameters) {
24
+ this.nodeShapesByIdentifier = parameters.nodeShapesByIdentifier;
25
+ this.ontologiesByIdentifier = parameters.ontologiesByIdentifier;
26
+ this.propertyGroupsByIdentifier = parameters.propertyGroupsByIdentifier;
27
+ this.propertyShapesByIdentifier = parameters.propertyShapesByIdentifier;
28
+ }
29
+ get nodeShapes() {
30
+ return [...this.nodeShapesByIdentifier.values()];
31
+ }
32
+ nodeShapeByIdentifier(identifier) {
33
+ const nodeShape = this.nodeShapesByIdentifier.get(identifier);
34
+ return nodeShape
35
+ ? Either.of(nodeShape)
36
+ : Left(new Error(`no such node shape ${Resource.Identifier.toString(identifier)}`));
37
+ }
38
+ get ontologies() {
39
+ return [...this.ontologiesByIdentifier.values()];
40
+ }
41
+ ontologyByIdentifier(identifier) {
42
+ const ontology = this.ontologiesByIdentifier.get(identifier);
43
+ return ontology
44
+ ? Either.of(ontology)
45
+ : Left(new Error(`no such ontology ${Resource.Identifier.toString(identifier)}`));
46
+ }
47
+ propertyGroupByIdentifier(identifier) {
48
+ const propertyGroup = this.propertyGroupsByIdentifier.get(identifier);
49
+ return propertyGroup
50
+ ? Either.of(propertyGroup)
51
+ : Left(new Error(`no such property group ${Resource.Identifier.toString(identifier)}`));
52
+ }
53
+ get propertyGroups() {
54
+ return [...this.propertyGroupsByIdentifier.values()];
55
+ }
56
+ propertyShapeByIdentifier(identifier) {
57
+ const propertyShape = this.propertyShapesByIdentifier.get(identifier);
58
+ return propertyShape
59
+ ? Either.of(propertyShape)
60
+ : Left(new Error(`no such property shape ${Resource.Identifier.toString(identifier)}`));
61
+ }
62
+ get propertyShapes() {
63
+ return [...this.propertyShapesByIdentifier.values()];
64
+ }
65
+ shapeByIdentifier(identifier) {
66
+ return this.nodeShapeByIdentifier(identifier).alt(this.propertyShapeByIdentifier(identifier));
67
+ }
68
+ }
69
+ __decorate([
70
+ Memoize()
71
+ ], ShapesGraph.prototype, "nodeShapes", null);
72
+ __decorate([
73
+ Memoize()
74
+ ], ShapesGraph.prototype, "ontologies", null);
75
+ __decorate([
76
+ Memoize()
77
+ ], ShapesGraph.prototype, "propertyGroups", null);
78
+ __decorate([
79
+ Memoize()
80
+ ], ShapesGraph.prototype, "propertyShapes", null);
81
+ (function (ShapesGraph) {
82
+ class Factory {
83
+ preferredLanguages;
84
+ constructor(parameters) {
85
+ this.preferredLanguages = parameters?.preferredLanguages ?? ["en", ""];
86
+ }
87
+ createShapesGraph({ dataset, ignoreUndefinedShapes, }) {
88
+ function datasetHasMatch(subject, predicate, object, graph) {
89
+ for (const _ of dataset.match(subject, predicate, object, graph)) {
90
+ return true;
91
+ }
92
+ return false;
93
+ }
94
+ const resourceSet = new ResourceSet(dataset);
95
+ const nodeShapesByIdentifier = new TermMap();
96
+ const ontologiesByIdentifier = new TermMap();
97
+ const propertyGroupsByIdentifier = new TermMap();
98
+ const propertyShapesByIdentifier = new TermMap();
99
+ // Have to instantiate ShapesGraph here so the shapes have references to it
100
+ // Pass in the mutable TermMap's and then mutate them
101
+ const shapesGraph = new ShapesGraph({
102
+ nodeShapesByIdentifier,
103
+ ontologiesByIdentifier,
104
+ propertyGroupsByIdentifier,
105
+ propertyShapesByIdentifier,
106
+ });
107
+ return Either.encase(() => {
108
+ function readGraph() {
109
+ const graphs = new TermSet();
110
+ for (const quad of dataset) {
111
+ graphs.add(quad.graph);
112
+ }
113
+ if (graphs.size !== 1) {
114
+ return undefined;
115
+ }
116
+ const graph = [...graphs.values()][0];
117
+ switch (graph.termType) {
118
+ case "BlankNode":
119
+ case "DefaultGraph":
120
+ case "NamedNode":
121
+ return graph;
122
+ default:
123
+ throw new RangeError(`expected NamedNode or default graph, actual ${graph.termType}`);
124
+ }
125
+ }
126
+ const graph = readGraph();
127
+ // Read ontologies
128
+ for (const ontologyResource of resourceSet.instancesOf(owl.Ontology, {
129
+ graph,
130
+ })) {
131
+ if (ontologiesByIdentifier.has(ontologyResource.identifier)) {
132
+ continue;
133
+ }
134
+ this.createOntology({
135
+ resource: ontologyResource,
136
+ shapesGraph,
137
+ }).ifRight((ontology) => ontologiesByIdentifier.set(ontologyResource.identifier, ontology));
138
+ }
139
+ // Read property groups
140
+ for (const propertyGroupResource of resourceSet.instancesOf(sh.PropertyGroup, { graph })) {
141
+ if (propertyGroupResource.identifier.termType !== "NamedNode") {
142
+ continue;
143
+ }
144
+ if (propertyGroupsByIdentifier.has(propertyGroupResource.identifier)) {
145
+ continue;
146
+ }
147
+ this.createPropertyGroup({
148
+ resource: propertyGroupResource,
149
+ shapesGraph,
150
+ }).ifRight((propertyGroup) => propertyGroupsByIdentifier.set(propertyGroupResource.identifier, propertyGroup));
151
+ }
152
+ // Read shapes
153
+ // Collect the shape identifiers in sets
154
+ const shapeNodeSet = new TermSet();
155
+ // Utility function for adding to the shapeNodeSet
156
+ function addShapeNode(shapeNode) {
157
+ switch (shapeNode.termType) {
158
+ case "BlankNode":
159
+ case "NamedNode":
160
+ shapeNodeSet.add(shapeNode);
161
+ return true;
162
+ default:
163
+ throw new RangeError(`unexpected shape node identifier term type: ${shapeNode.termType}`);
164
+ }
165
+ }
166
+ // Test each shape condition
167
+ // https://www.w3.org/TR/shacl/#shapes
168
+ // Subject is a SHACL instance of sh:NodeShape or sh:PropertyShape
169
+ for (const rdfType of [sh.NodeShape, sh.PropertyShape]) {
170
+ for (const resource of resourceSet.instancesOf(rdfType, {
171
+ graph,
172
+ })) {
173
+ addShapeNode(resource.identifier);
174
+ }
175
+ }
176
+ // Subject of a triple with sh:targetClass, sh:targetNode, sh:targetObjectsOf, or sh:targetSubjectsOf predicate
177
+ for (const predicate of [
178
+ sh.targetClass,
179
+ sh.targetNode,
180
+ sh.targetObjectsOf,
181
+ sh.targetSubjectsOf,
182
+ ]) {
183
+ for (const quad of dataset.match(null, predicate, null, graph)) {
184
+ addShapeNode(quad.subject);
185
+ }
186
+ }
187
+ // Subject of a triple that has a parameter as predicate
188
+ // https://www.w3.org/TR/shacl/#constraints
189
+ // https://www.w3.org/TR/shacl/#core-components
190
+ for (const predicate of [
191
+ sh.class,
192
+ sh.datatype,
193
+ sh.nodeKind,
194
+ sh.minCount,
195
+ sh.maxCount,
196
+ sh.minExclusive,
197
+ sh.minInclusive,
198
+ sh.maxExclusive,
199
+ sh.maxInclusive,
200
+ sh.minLength,
201
+ sh.maxLength,
202
+ sh.pattern,
203
+ sh.languageIn,
204
+ sh.uniqueLang,
205
+ sh.equals,
206
+ sh.disjoint,
207
+ sh.lessThan,
208
+ sh.lessThanOrEquals,
209
+ sh.not,
210
+ sh.and,
211
+ sh.or,
212
+ sh.xone,
213
+ sh.node,
214
+ sh.property,
215
+ sh.qualifiedValueShape,
216
+ sh.qualifiedMinCount,
217
+ sh.qualifiedMaxCount,
218
+ sh.closed,
219
+ sh.ignoredProperties,
220
+ sh.hasValue,
221
+ sh.in,
222
+ ]) {
223
+ for (const quad of dataset.match(null, predicate, null, graph)) {
224
+ addShapeNode(quad.subject);
225
+ }
226
+ }
227
+ // Object of a shape-expecting, non-list-taking parameter such as sh:node
228
+ for (const predicate of [sh.node, sh.not, sh.property]) {
229
+ for (const quad of dataset.match(null, predicate, null, graph)) {
230
+ addShapeNode(quad.object);
231
+ if (!ignoreUndefinedShapes && !datasetHasMatch(quad.object)) {
232
+ throw new Error(`undefined shape: ${Resource.Identifier.toString(quad.object)}`);
233
+ }
234
+ }
235
+ }
236
+ // Member of a SHACL list that is a value of a shape-expecting and list-taking parameter such as sh:or
237
+ for (const predicate of [sh.and, sh.or, sh.xone]) {
238
+ for (const quad of dataset.match(null, predicate, null, graph)) {
239
+ switch (quad.object.termType) {
240
+ case "BlankNode":
241
+ case "NamedNode":
242
+ break;
243
+ default:
244
+ throw new RangeError(`expected list term to be a blank or named node, not ${quad.object.termType}`);
245
+ }
246
+ for (const value of resourceSet
247
+ .resource(quad.object)
248
+ .toList()
249
+ .unsafeCoerce()) {
250
+ const identifier = value.toIdentifier().unsafeCoerce();
251
+ addShapeNode(identifier);
252
+ if (!ignoreUndefinedShapes && !datasetHasMatch(identifier)) {
253
+ throw new Error(`undefined shape: ${Resource.Identifier.toString(identifier)}`);
254
+ }
255
+ }
256
+ }
257
+ }
258
+ // Separate shapes into node and property shapes.
259
+ for (const shapeNode of shapeNodeSet) {
260
+ if (dataset.match(shapeNode, sh.path, null, graph).size > 0) {
261
+ // A property shape is a shape in the shapes graph that is the subject of a triple that has sh:path as its predicate. A shape has at most one value for sh:path. Each value of sh:path in a shape must be a well-formed SHACL property path. It is recommended, but not required, for a property shape to be declared as a SHACL instance of sh:PropertyShape. SHACL instances of sh:PropertyShape have one value for the property sh:path.
262
+ propertyShapesByIdentifier.set(shapeNode, this.createPropertyShape({
263
+ resource: resourceSet.resource(shapeNode),
264
+ shapesGraph,
265
+ }).unsafeCoerce());
266
+ }
267
+ else {
268
+ // A node shape is a shape in the shapes graph that is not the subject of a triple with sh:path as its predicate. It is recommended, but not required, for a node shape to be declared as a SHACL instance of sh:NodeShape. SHACL instances of sh:NodeShape cannot have a value for the property sh:path.
269
+ nodeShapesByIdentifier.set(shapeNode, this.createNodeShape({
270
+ resource: resourceSet.resource(shapeNode),
271
+ shapesGraph,
272
+ }).unsafeCoerce());
273
+ }
274
+ }
275
+ return shapesGraph;
276
+ });
277
+ }
278
+ }
279
+ ShapesGraph.Factory = Factory;
280
+ class DefaultFactory extends Factory {
281
+ createNodeShape({ resource, shapesGraph, }) {
282
+ return generated.ShaclCoreNodeShape.$fromRdf(resource, {
283
+ ignoreRdfType: true,
284
+ preferredLanguages: this.preferredLanguages,
285
+ }).map((generatedShape) => new NodeShape(generatedShape, shapesGraph));
286
+ }
287
+ createOntology({ resource, }) {
288
+ return generated.OwlOntology.$fromRdf(resource, {
289
+ ignoreRdfType: true,
290
+ preferredLanguages: this.preferredLanguages,
291
+ }).map((generatedOntology) => new Ontology(generatedOntology));
292
+ }
293
+ createPropertyGroup({ resource, }) {
294
+ return generated.ShaclCorePropertyGroup.$fromRdf(resource, {
295
+ ignoreRdfType: true,
296
+ preferredLanguages: this.preferredLanguages,
297
+ }).map((propertyGroup) => new PropertyGroup(propertyGroup));
298
+ }
299
+ createPropertyShape({ resource, shapesGraph, }) {
300
+ return generated.ShaclCorePropertyShape.$fromRdf(resource, {
301
+ ignoreRdfType: true,
302
+ preferredLanguages: this.preferredLanguages,
303
+ }).map((generatedShape) => new PropertyShape(generatedShape, shapesGraph));
304
+ }
305
+ }
306
+ const defaultFactory = new DefaultFactory();
307
+ function create(parameters) {
308
+ return defaultFactory.createShapesGraph(parameters);
309
+ }
310
+ ShapesGraph.create = create;
311
+ })(ShapesGraph || (ShapesGraph = {}));
2
312
  //# sourceMappingURL=ShapesGraph.js.map