@oml/owl 0.7.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.
Files changed (46) hide show
  1. package/README.md +46 -0
  2. package/out/index.d.ts +10 -0
  3. package/out/index.js +12 -0
  4. package/out/index.js.map +1 -0
  5. package/out/owl/owl-abox.d.ts +79 -0
  6. package/out/owl/owl-abox.js +765 -0
  7. package/out/owl/owl-abox.js.map +1 -0
  8. package/out/owl/owl-imports.d.ts +9 -0
  9. package/out/owl/owl-imports.js +102 -0
  10. package/out/owl/owl-imports.js.map +1 -0
  11. package/out/owl/owl-interfaces.d.ts +121 -0
  12. package/out/owl/owl-interfaces.js +3 -0
  13. package/out/owl/owl-interfaces.js.map +1 -0
  14. package/out/owl/owl-mapper.d.ts +80 -0
  15. package/out/owl/owl-mapper.js +1217 -0
  16. package/out/owl/owl-mapper.js.map +1 -0
  17. package/out/owl/owl-service.d.ts +65 -0
  18. package/out/owl/owl-service.js +552 -0
  19. package/out/owl/owl-service.js.map +1 -0
  20. package/out/owl/owl-shacl.d.ts +28 -0
  21. package/out/owl/owl-shacl.js +337 -0
  22. package/out/owl/owl-shacl.js.map +1 -0
  23. package/out/owl/owl-sparql.d.ts +71 -0
  24. package/out/owl/owl-sparql.js +260 -0
  25. package/out/owl/owl-sparql.js.map +1 -0
  26. package/out/owl/owl-store.d.ts +32 -0
  27. package/out/owl/owl-store.js +142 -0
  28. package/out/owl/owl-store.js.map +1 -0
  29. package/out/owl/owl-tbox.d.ts +98 -0
  30. package/out/owl/owl-tbox.js +575 -0
  31. package/out/owl/owl-tbox.js.map +1 -0
  32. package/out/owl-module.d.ts +15 -0
  33. package/out/owl-module.js +22 -0
  34. package/out/owl-module.js.map +1 -0
  35. package/package.json +52 -0
  36. package/src/index.ts +12 -0
  37. package/src/owl/owl-abox.ts +930 -0
  38. package/src/owl/owl-imports.ts +108 -0
  39. package/src/owl/owl-interfaces.ts +145 -0
  40. package/src/owl/owl-mapper.ts +1510 -0
  41. package/src/owl/owl-service.ts +642 -0
  42. package/src/owl/owl-shacl.ts +400 -0
  43. package/src/owl/owl-sparql.ts +317 -0
  44. package/src/owl/owl-store.ts +173 -0
  45. package/src/owl/owl-tbox.ts +727 -0
  46. package/src/owl-module.ts +52 -0
@@ -0,0 +1,1510 @@
1
+ // Copyright (c) 2026 Modelware. All rights reserved.
2
+
3
+ import { DataFactory, Quad } from 'n3';
4
+ import type { Quad_Object, Quad_Predicate, Quad_Subject } from 'n3';
5
+ import type {
6
+ Argument,
7
+ Annotation,
8
+ AnnotationProperty,
9
+ AnonymousInstance,
10
+ Aspect,
11
+ BuiltIn,
12
+ Concept,
13
+ ConceptInstance,
14
+ EntityEquivalenceAxiom,
15
+ Import,
16
+ InstanceEnumerationAxiom,
17
+ KeyAxiom,
18
+ Literal,
19
+ LiteralEnumerationAxiom,
20
+ Ontology,
21
+ PropertyCardinalityRestrictionAxiom,
22
+ PropertyEquivalenceAxiom,
23
+ PropertyRangeRestrictionAxiom,
24
+ PropertyRestrictionAxiom,
25
+ PropertySelfRestrictionAxiom,
26
+ PropertyValueAssertion,
27
+ PropertyValueRestrictionAxiom,
28
+ Predicate,
29
+ RelationBase,
30
+ RelationEntity,
31
+ RelationInstance,
32
+ ReverseRelation,
33
+ Rule,
34
+ Scalar,
35
+ ScalarEquivalenceAxiom,
36
+ ScalarProperty,
37
+ SemanticProperty,
38
+ SpecializationAxiom,
39
+ TypeAssertion,
40
+ UnreifiedRelation,
41
+ } from '@oml/language';
42
+ import {
43
+ isAnnotationProperty,
44
+ isAnonymousConceptInstance,
45
+ isAnonymousRelationInstance,
46
+ isAspect,
47
+ isBooleanLiteral,
48
+ isBuiltInPredicate,
49
+ isBuiltIn,
50
+ isConcept,
51
+ isConceptInstance,
52
+ isDecimalLiteral,
53
+ isDifferentFromPredicate,
54
+ isDescription,
55
+ isDescriptionBundle,
56
+ isDoubleLiteral,
57
+ isIntegerLiteral,
58
+ isOntology,
59
+ isPropertyPredicate,
60
+ isPropertyCardinalityRestrictionAxiom,
61
+ isPropertyRangeRestrictionAxiom,
62
+ isPropertySelfRestrictionAxiom,
63
+ isPropertyValueRestrictionAxiom,
64
+ isQuotedLiteral,
65
+ isRelation,
66
+ isRelationEntityPredicate,
67
+ isRelationEntity,
68
+ isRelationInstance,
69
+ isReverseRelation,
70
+ isRule,
71
+ isSameAsPredicate,
72
+ isScalar,
73
+ isScalarProperty,
74
+ isTypePredicate,
75
+ isUnreifiedRelation,
76
+ isVocabulary,
77
+ isVocabularyBundle,
78
+ } from '@oml/language';
79
+
80
+ type PrefixMap = Record<string, string>;
81
+
82
+ interface MappingContext {
83
+ ontologyIri: string;
84
+ namespace: string;
85
+ prefix: string;
86
+ prefixes: PrefixMap;
87
+ }
88
+
89
+ export interface Oml2OwlMapperOptions {
90
+ emitSwrlRules?: boolean;
91
+ emitRelationEntitySwrlRules?: boolean;
92
+ }
93
+
94
+ export const OWL_ONTOLOGY_IRI = 'http://opencaesar.io/oml';
95
+ export const OWL_ONTOLOGY_NAMESPACE = 'http://opencaesar.io/oml#';
96
+ export const OWL_ONTOLOGY_PREFIX = 'oml';
97
+
98
+ const RDF = {
99
+ type: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type',
100
+ first: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#first',
101
+ rest: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest',
102
+ nil: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil',
103
+ langRange: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langRange',
104
+ langString: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#langString',
105
+ };
106
+
107
+ const RDFS = {
108
+ Datatype: 'http://www.w3.org/2000/01/rdf-schema#Datatype',
109
+ label: 'http://www.w3.org/2000/01/rdf-schema#label',
110
+ subClassOf: 'http://www.w3.org/2000/01/rdf-schema#subClassOf',
111
+ subPropertyOf: 'http://www.w3.org/2000/01/rdf-schema#subPropertyOf',
112
+ domain: 'http://www.w3.org/2000/01/rdf-schema#domain',
113
+ range: 'http://www.w3.org/2000/01/rdf-schema#range',
114
+ };
115
+
116
+ const OWL = {
117
+ Ontology: 'http://www.w3.org/2002/07/owl#Ontology',
118
+ Class: 'http://www.w3.org/2002/07/owl#Class',
119
+ ObjectProperty: 'http://www.w3.org/2002/07/owl#ObjectProperty',
120
+ DatatypeProperty: 'http://www.w3.org/2002/07/owl#DatatypeProperty',
121
+ AnnotationProperty: 'http://www.w3.org/2002/07/owl#AnnotationProperty',
122
+ Datatype: 'http://www.w3.org/2002/07/owl#Datatype',
123
+ FunctionalProperty: 'http://www.w3.org/2002/07/owl#FunctionalProperty',
124
+ InverseFunctionalProperty: 'http://www.w3.org/2002/07/owl#InverseFunctionalProperty',
125
+ SymmetricProperty: 'http://www.w3.org/2002/07/owl#SymmetricProperty',
126
+ AsymmetricProperty: 'http://www.w3.org/2002/07/owl#AsymmetricProperty',
127
+ ReflexiveProperty: 'http://www.w3.org/2002/07/owl#ReflexiveProperty',
128
+ IrreflexiveProperty: 'http://www.w3.org/2002/07/owl#IrreflexiveProperty',
129
+ TransitiveProperty: 'http://www.w3.org/2002/07/owl#TransitiveProperty',
130
+ Restriction: 'http://www.w3.org/2002/07/owl#Restriction',
131
+ onProperty: 'http://www.w3.org/2002/07/owl#onProperty',
132
+ onClass: 'http://www.w3.org/2002/07/owl#onClass',
133
+ onDataRange: 'http://www.w3.org/2002/07/owl#onDataRange',
134
+ onDatatype: 'http://www.w3.org/2002/07/owl#onDatatype',
135
+ withRestrictions: 'http://www.w3.org/2002/07/owl#withRestrictions',
136
+ someValuesFrom: 'http://www.w3.org/2002/07/owl#someValuesFrom',
137
+ allValuesFrom: 'http://www.w3.org/2002/07/owl#allValuesFrom',
138
+ minCardinality: 'http://www.w3.org/2002/07/owl#minCardinality',
139
+ maxCardinality: 'http://www.w3.org/2002/07/owl#maxCardinality',
140
+ cardinality: 'http://www.w3.org/2002/07/owl#cardinality',
141
+ hasValue: 'http://www.w3.org/2002/07/owl#hasValue',
142
+ hasSelf: 'http://www.w3.org/2002/07/owl#hasSelf',
143
+ hasKey: 'http://www.w3.org/2002/07/owl#hasKey',
144
+ inverseOf: 'http://www.w3.org/2002/07/owl#inverseOf',
145
+ equivalentClass: 'http://www.w3.org/2002/07/owl#equivalentClass',
146
+ equivalentProperty: 'http://www.w3.org/2002/07/owl#equivalentProperty',
147
+ subPropertyOf: 'http://www.w3.org/2002/07/owl#subPropertyOf',
148
+ imports: 'http://www.w3.org/2002/07/owl#imports',
149
+ NamedIndividual: 'http://www.w3.org/2002/07/owl#NamedIndividual',
150
+ oneOf: 'http://www.w3.org/2002/07/owl#oneOf',
151
+ };
152
+
153
+ const XSD = {
154
+ boolean: 'http://www.w3.org/2001/XMLSchema#boolean',
155
+ decimal: 'http://www.w3.org/2001/XMLSchema#decimal',
156
+ double: 'http://www.w3.org/2001/XMLSchema#double',
157
+ integer: 'http://www.w3.org/2001/XMLSchema#integer',
158
+ string: 'http://www.w3.org/2001/XMLSchema#string',
159
+ length: 'http://www.w3.org/2001/XMLSchema#length',
160
+ minLength: 'http://www.w3.org/2001/XMLSchema#minLength',
161
+ maxLength: 'http://www.w3.org/2001/XMLSchema#maxLength',
162
+ minInclusive: 'http://www.w3.org/2001/XMLSchema#minInclusive',
163
+ maxInclusive: 'http://www.w3.org/2001/XMLSchema#maxInclusive',
164
+ minExclusive: 'http://www.w3.org/2001/XMLSchema#minExclusive',
165
+ maxExclusive: 'http://www.w3.org/2001/XMLSchema#maxExclusive',
166
+ pattern: 'http://www.w3.org/2001/XMLSchema#pattern',
167
+ };
168
+
169
+ const OML = {
170
+ ns: OWL_ONTOLOGY_NAMESPACE,
171
+ type: `${OWL_ONTOLOGY_NAMESPACE}type`,
172
+ name: `${OWL_ONTOLOGY_NAMESPACE}name`,
173
+ namespace: `${OWL_ONTOLOGY_NAMESPACE}namespace`,
174
+ prefix: `${OWL_ONTOLOGY_NAMESPACE}prefix`,
175
+ Aspect: `${OWL_ONTOLOGY_NAMESPACE}Aspect`,
176
+ Concept: `${OWL_ONTOLOGY_NAMESPACE}Concept`,
177
+ RelationEntity: `${OWL_ONTOLOGY_NAMESPACE}RelationEntity`,
178
+ RelationInstance: `${OWL_ONTOLOGY_NAMESPACE}RelationInstance`,
179
+ ConceptInstance: `${OWL_ONTOLOGY_NAMESPACE}ConceptInstance`,
180
+ Scalar: `${OWL_ONTOLOGY_NAMESPACE}Scalar`,
181
+ ForwardRelation: `${OWL_ONTOLOGY_NAMESPACE}ForwardRelation`,
182
+ UnreifiedRelation: `${OWL_ONTOLOGY_NAMESPACE}UnreifiedRelation`,
183
+ ReverseRelation: `${OWL_ONTOLOGY_NAMESPACE}ReverseRelation`,
184
+ relationEntity: `${OWL_ONTOLOGY_NAMESPACE}relationEntity`,
185
+ relationBase: `${OWL_ONTOLOGY_NAMESPACE}relationBase`,
186
+ hasSource: `${OWL_ONTOLOGY_NAMESPACE}hasSource`,
187
+ hasTarget: `${OWL_ONTOLOGY_NAMESPACE}hasTarget`,
188
+ Rule: `${OWL_ONTOLOGY_NAMESPACE}Rule`,
189
+ BuiltIn: `${OWL_ONTOLOGY_NAMESPACE}BuiltIn`,
190
+ Vocabulary: `${OWL_ONTOLOGY_NAMESPACE}Vocabulary`,
191
+ VocabularyBundle: `${OWL_ONTOLOGY_NAMESPACE}VocabularyBundle`,
192
+ Description: `${OWL_ONTOLOGY_NAMESPACE}Description`,
193
+ DescriptionBundle: `${OWL_ONTOLOGY_NAMESPACE}DescriptionBundle`,
194
+ };
195
+
196
+ const OML_TERM_TYPES = {
197
+ annotation: OWL.AnnotationProperty,
198
+ object: OWL.ObjectProperty,
199
+ datatype: OWL.DatatypeProperty,
200
+ class: OWL.Class,
201
+ } as const;
202
+
203
+ const OML_TERMS: Array<{ iri: string; rdfType: string }> = [
204
+ { iri: OML.type, rdfType: OML_TERM_TYPES.annotation },
205
+ { iri: OML.name, rdfType: OML_TERM_TYPES.annotation },
206
+ { iri: OML.namespace, rdfType: OML_TERM_TYPES.annotation },
207
+ { iri: OML.prefix, rdfType: OML_TERM_TYPES.annotation },
208
+ { iri: OML.relationEntity, rdfType: OML_TERM_TYPES.object },
209
+ { iri: OML.relationBase, rdfType: OML_TERM_TYPES.object },
210
+ { iri: OML.hasSource, rdfType: OML_TERM_TYPES.object },
211
+ { iri: OML.hasTarget, rdfType: OML_TERM_TYPES.object },
212
+ { iri: OML.Aspect, rdfType: OML_TERM_TYPES.class },
213
+ { iri: OML.Concept, rdfType: OML_TERM_TYPES.class },
214
+ { iri: OML.RelationEntity, rdfType: OML_TERM_TYPES.class },
215
+ { iri: OML.RelationInstance, rdfType: OML_TERM_TYPES.class },
216
+ { iri: OML.ConceptInstance, rdfType: OML_TERM_TYPES.class },
217
+ { iri: OML.Scalar, rdfType: OML_TERM_TYPES.class },
218
+ { iri: OML.ForwardRelation, rdfType: OML_TERM_TYPES.class },
219
+ { iri: OML.UnreifiedRelation, rdfType: OML_TERM_TYPES.class },
220
+ { iri: OML.ReverseRelation, rdfType: OML_TERM_TYPES.class },
221
+ { iri: OML.Rule, rdfType: OML_TERM_TYPES.class },
222
+ { iri: OML.BuiltIn, rdfType: OML_TERM_TYPES.class },
223
+ { iri: OML.Vocabulary, rdfType: OML_TERM_TYPES.class },
224
+ { iri: OML.VocabularyBundle, rdfType: OML_TERM_TYPES.class },
225
+ { iri: OML.Description, rdfType: OML_TERM_TYPES.class },
226
+ { iri: OML.DescriptionBundle, rdfType: OML_TERM_TYPES.class },
227
+ ];
228
+
229
+ const SWRL = {
230
+ Imp: 'http://www.w3.org/2003/11/swrl#Imp',
231
+ AtomList: 'http://www.w3.org/2003/11/swrl#AtomList',
232
+ body: 'http://www.w3.org/2003/11/swrl#body',
233
+ head: 'http://www.w3.org/2003/11/swrl#head',
234
+ ClassAtom: 'http://www.w3.org/2003/11/swrl#ClassAtom',
235
+ DataRangeAtom: 'http://www.w3.org/2003/11/swrl#DataRangeAtom',
236
+ IndividualPropertyAtom: 'http://www.w3.org/2003/11/swrl#IndividualPropertyAtom',
237
+ DatavaluedPropertyAtom: 'http://www.w3.org/2003/11/swrl#DatavaluedPropertyAtom',
238
+ SameIndividualAtom: 'http://www.w3.org/2003/11/swrl#SameIndividualAtom',
239
+ DifferentIndividualsAtom: 'http://www.w3.org/2003/11/swrl#DifferentIndividualsAtom',
240
+ BuiltinAtom: 'http://www.w3.org/2003/11/swrl#BuiltinAtom',
241
+ Variable: 'http://www.w3.org/2003/11/swrl#Variable',
242
+ classPredicate: 'http://www.w3.org/2003/11/swrl#classPredicate',
243
+ dataRange: 'http://www.w3.org/2003/11/swrl#dataRange',
244
+ propertyPredicate: 'http://www.w3.org/2003/11/swrl#propertyPredicate',
245
+ argument1: 'http://www.w3.org/2003/11/swrl#argument1',
246
+ argument2: 'http://www.w3.org/2003/11/swrl#argument2',
247
+ builtin: 'http://www.w3.org/2003/11/swrl#builtin',
248
+ arguments: 'http://www.w3.org/2003/11/swrl#arguments',
249
+ };
250
+
251
+ const BUILT_IN_ONTOLOGIES = new Set([
252
+ 'http://www.w3.org/2001/XMLSchema',
253
+ 'http://www.w3.org/1999/02/22-rdf-syntax-ns',
254
+ 'http://www.w3.org/2000/01/rdf-schema',
255
+ 'http://www.w3.org/2002/07/owl',
256
+ 'http://www.w3.org/2003/11/swrl',
257
+ 'http://www.w3.org/2003/11/swrlb',
258
+ ]);
259
+
260
+ const { namedNode, literal, quad } = DataFactory;
261
+ type TermNode = ReturnType<typeof namedNode>;
262
+
263
+ function fnv1a(input: string): string {
264
+ let hash = 2166136261;
265
+ for (let i = 0; i < input.length; i += 1) {
266
+ hash ^= input.charCodeAt(i);
267
+ hash = (hash * 16777619) >>> 0;
268
+ }
269
+ return hash.toString(16);
270
+ }
271
+
272
+ function skolemize(namespace: string, ...inputs: string[]): ReturnType<typeof namedNode> {
273
+ if (inputs.length === 0) {
274
+ throw new Error('skolemize requires at least one input.');
275
+ }
276
+ const [kind, ...semanticInputs] = inputs;
277
+ const identity = semanticInputs.length > 0 ? semanticInputs.join('|') : kind;
278
+ const hash = fnv1a(identity);
279
+ return namedNode(`${namespace}${kind}-${hash}`);
280
+ }
281
+
282
+ /**
283
+ * Maps an OML ontology AST into asserted RDF triples.
284
+ * This mirrors the high-level structure of the Java Oml2Owl mapping while focusing on asserted triples.
285
+ */
286
+ export class Oml2OwlMapper {
287
+ constructor(private readonly options: Oml2OwlMapperOptions = {
288
+ emitSwrlRules: true,
289
+ emitRelationEntitySwrlRules: true,
290
+ }) {}
291
+
292
+ toQuads(ontology: Ontology): Quad[] {
293
+ if (!isOntology(ontology)) {
294
+ return [];
295
+ }
296
+
297
+ const ctx = this.createContext(ontology);
298
+ const triples: Quad[] = [];
299
+ const ontologyNode = namedNode(ctx.ontologyIri);
300
+
301
+ // Ontology header
302
+ triples.push(this.quadWithGraph(ontologyNode, namedNode(RDF.type), namedNode(OWL.Ontology)));
303
+ triples.push(this.quadWithGraph(ontologyNode, namedNode(OML.type), namedNode(this.ontologyTypeIri(ontology))));
304
+ triples.push(this.quadWithGraph(ontologyNode, namedNode(OML.namespace), namedNode(ctx.namespace)));
305
+ triples.push(this.quadWithGraph(ontologyNode, namedNode(OML.prefix), literal(ctx.prefix)));
306
+
307
+ this.mapAnnotations(ontologyNode, (ontology as any).ownedAnnotations, ctx, triples);
308
+
309
+ // Imports
310
+ ontology.ownedImports?.forEach((imp) => {
311
+ const importedIri = this.importedOntologyIri(imp, ctx);
312
+ if (importedIri && !BUILT_IN_ONTOLOGIES.has(importedIri)) {
313
+ triples.push(this.quadWithGraph(ontologyNode, namedNode(OWL.imports), namedNode(importedIri)));
314
+ }
315
+ });
316
+ if (ctx.ontologyIri !== OWL_ONTOLOGY_IRI) {
317
+ triples.push(this.quadWithGraph(ontologyNode, namedNode(OWL.imports), namedNode(OWL_ONTOLOGY_IRI)));
318
+ }
319
+
320
+ if (isVocabulary(ontology)) {
321
+ ontology.ownedStatements?.forEach((stmt) => {
322
+ this.mapVocabularyStatement(stmt, ctx, triples);
323
+ });
324
+ } else if (isDescription(ontology)) {
325
+ ontology.ownedStatements?.forEach((stmt) => {
326
+ this.mapDescriptionStatement(stmt, ctx, triples);
327
+ });
328
+ }
329
+
330
+ return this.deduplicateQuads(triples);
331
+ }
332
+
333
+ private mapVocabularyStatement(stmt: unknown, ctx: MappingContext, triples: Quad[]): void {
334
+ if (isAspect(stmt)) {
335
+ this.mapAspect(stmt, ctx, triples);
336
+ } else if (isConcept(stmt)) {
337
+ this.mapConcept(stmt, ctx, triples);
338
+ } else if (isRelationEntity(stmt)) {
339
+ this.mapRelationEntity(stmt, ctx, triples);
340
+ } else if (isScalar(stmt)) {
341
+ this.mapScalar(stmt, ctx, triples);
342
+ } else if (isAnnotationProperty(stmt)) {
343
+ this.mapAnnotationProperty(stmt, ctx, triples);
344
+ } else if (isScalarProperty(stmt)) {
345
+ this.mapScalarProperty(stmt, ctx, triples);
346
+ } else if (isUnreifiedRelation(stmt)) {
347
+ this.mapUnreifiedRelation(stmt, ctx, triples);
348
+ } else if (isRelation(stmt) && isReverseRelation(stmt)) {
349
+ this.mapReverseRelation(stmt, ctx, triples);
350
+ } else if (isRule(stmt)) {
351
+ this.mapRule(stmt, ctx, triples);
352
+ } else if (isBuiltIn(stmt)) {
353
+ this.mapBuiltIn(stmt, ctx, triples);
354
+ }
355
+ }
356
+
357
+ private mapDescriptionStatement(stmt: unknown, ctx: MappingContext, triples: Quad[]): void {
358
+ if (isConceptInstance(stmt)) {
359
+ this.mapConceptInstance(stmt, ctx, triples);
360
+ } else if (isRelationInstance(stmt)) {
361
+ this.mapRelationInstance(stmt, ctx, triples);
362
+ }
363
+ }
364
+
365
+ private mapAspect(aspect: Aspect, ctx: MappingContext, triples: Quad[]): void {
366
+ const iri = this.elementIri(aspect, ctx);
367
+ if (!iri) return;
368
+ const node = namedNode(iri);
369
+
370
+ triples.push(this.quadWithGraph(node, namedNode(RDF.type), namedNode(OWL.Class)));
371
+ triples.push(this.quadWithGraph(node, namedNode(OML.type), namedNode(OML.Aspect)));
372
+ this.mapAnnotations(node, aspect.ownedAnnotations, ctx, triples);
373
+ this.applySpecializations(aspect.ownedSpecializations, node, ctx, triples);
374
+ this.applyEquivalences(aspect.ownedEquivalences, node, ctx, triples);
375
+ this.applyKeys(aspect.ownedKeys, node, ctx, triples);
376
+ this.applyPropertyRestrictions(aspect.ownedPropertyRestrictions, node, ctx, triples);
377
+ }
378
+
379
+ private mapConcept(concept: Concept, ctx: MappingContext, triples: Quad[]): void {
380
+ const iri = this.elementIri(concept, ctx);
381
+ if (!iri) return;
382
+ const node = namedNode(iri);
383
+
384
+ triples.push(this.quadWithGraph(node, namedNode(RDF.type), namedNode(OWL.Class)));
385
+ triples.push(this.quadWithGraph(node, namedNode(OML.type), namedNode(OML.Concept)));
386
+ this.mapAnnotations(node, concept.ownedAnnotations, ctx, triples);
387
+ this.applySpecializations(concept.ownedSpecializations, node, ctx, triples);
388
+ this.applyEquivalences(concept.ownedEquivalences, node, ctx, triples);
389
+ this.applyKeys(concept.ownedKeys, node, ctx, triples);
390
+ this.applyPropertyRestrictions(concept.ownedPropertyRestrictions, node, ctx, triples);
391
+ this.applyInstanceEnumeration(concept.ownedEnumeration, node, ctx, triples);
392
+ }
393
+
394
+ private mapRelationEntity(entity: RelationEntity, ctx: MappingContext, triples: Quad[]): void {
395
+ const classIri = this.elementIri(entity, ctx);
396
+ if (!classIri) return;
397
+
398
+ const classNode = namedNode(classIri);
399
+ const forwardIri = this.getForwardIri(entity, ctx);
400
+ const forwardNode = namedNode(forwardIri);
401
+
402
+ triples.push(this.quadWithGraph(classNode, namedNode(RDF.type), namedNode(OWL.Class)));
403
+ triples.push(this.quadWithGraph(classNode, namedNode(OML.type), namedNode(OML.RelationEntity)));
404
+ this.mapAnnotations(classNode, entity.ownedAnnotations, ctx, triples);
405
+
406
+ // Forward relation object property
407
+ triples.push(this.quadWithGraph(forwardNode, namedNode(RDF.type), namedNode(OWL.ObjectProperty)));
408
+ triples.push(this.quadWithGraph(forwardNode, namedNode(OML.type), namedNode(OML.ForwardRelation)));
409
+ triples.push(this.quadWithGraph(forwardNode, namedNode(OML.relationEntity), classNode));
410
+ this.mapAnnotations(forwardNode, entity.forwardRelation?.ownedAnnotations, ctx, triples);
411
+
412
+ this.applyDomainRange(forwardNode, entity.sources, entity.targets, ctx, triples);
413
+ this.applyObjectPropertyCharacteristics(forwardNode, entity, triples);
414
+
415
+ if (entity.reverseRelation) {
416
+ this.mapReverseRelation(entity.reverseRelation, ctx, triples, entity);
417
+ }
418
+
419
+ this.applySpecializations(entity.ownedSpecializations, classNode, ctx, triples);
420
+ this.applyEquivalences(entity.ownedEquivalences, classNode, ctx, triples);
421
+ this.applyKeys(entity.ownedKeys, classNode, ctx, triples);
422
+ this.applyPropertyRestrictions(entity.ownedPropertyRestrictions, classNode, ctx, triples);
423
+ if (this.options.emitSwrlRules !== false || this.options.emitRelationEntitySwrlRules === true) {
424
+ this.mapRelationEntityForwardRule(classIri, forwardIri, ctx, triples);
425
+ }
426
+ }
427
+
428
+ private mapUnreifiedRelation(relation: UnreifiedRelation, ctx: MappingContext, triples: Quad[]): void {
429
+ const forwardIri = this.elementIri(relation, ctx);
430
+ if (!forwardIri) return;
431
+ const forwardNode = namedNode(forwardIri);
432
+
433
+ triples.push(this.quadWithGraph(forwardNode, namedNode(RDF.type), namedNode(OWL.ObjectProperty)));
434
+ triples.push(this.quadWithGraph(forwardNode, namedNode(OML.type), namedNode(OML.UnreifiedRelation)));
435
+ this.mapAnnotations(forwardNode, relation.ownedAnnotations, ctx, triples);
436
+
437
+ this.applyDomainRange(forwardNode, relation.sources, relation.targets, ctx, triples);
438
+ this.applyObjectPropertyCharacteristics(forwardNode, relation, triples);
439
+
440
+ if (relation.reverseRelation) {
441
+ this.mapReverseRelation(relation.reverseRelation, ctx, triples, relation);
442
+ }
443
+
444
+ this.applySpecializations(relation.ownedSpecializations, forwardNode, ctx, triples, true);
445
+ this.applyPropertyEquivalences(relation.ownedEquivalences, forwardNode, ctx, triples);
446
+ }
447
+
448
+ private mapReverseRelation(
449
+ reverse: ReverseRelation,
450
+ ctx: MappingContext,
451
+ triples: Quad[],
452
+ relationBase?: RelationBase,
453
+ ): void {
454
+ const base = relationBase ?? (reverse.$container as RelationBase);
455
+ const reverseIri = this.elementIri(reverse, ctx);
456
+ const forwardIri = this.getForwardIri(base, ctx);
457
+ const baseIri = this.elementIri(base, ctx);
458
+ if (!reverseIri || !baseIri) return;
459
+
460
+ const reverseNode = namedNode(reverseIri);
461
+ triples.push(this.quadWithGraph(reverseNode, namedNode(RDF.type), namedNode(OWL.ObjectProperty)));
462
+ triples.push(this.quadWithGraph(reverseNode, namedNode(OML.type), namedNode(OML.ReverseRelation)));
463
+ triples.push(this.quadWithGraph(reverseNode, namedNode(OML.relationBase), namedNode(baseIri)));
464
+ triples.push(this.quadWithGraph(reverseNode, namedNode(OWL.inverseOf), namedNode(forwardIri)));
465
+ this.mapAnnotations(reverseNode, reverse.ownedAnnotations, ctx, triples);
466
+ }
467
+
468
+ private mapScalar(scalar: Scalar, ctx: MappingContext, triples: Quad[]): void {
469
+ const iri = this.elementIri(scalar, ctx);
470
+ if (!iri) return;
471
+ const node = namedNode(iri);
472
+
473
+ triples.push(this.quadWithGraph(node, namedNode(RDF.type), namedNode(RDFS.Datatype)));
474
+ triples.push(this.quadWithGraph(node, namedNode(OML.type), namedNode(OML.Scalar)));
475
+ this.mapAnnotations(node, scalar.ownedAnnotations, ctx, triples);
476
+ this.applySpecializations(scalar.ownedSpecializations, node, ctx, triples);
477
+ this.applyScalarEquivalences(scalar.ownedEquivalences, node, ctx, triples);
478
+ this.applyScalarEnumeration(scalar.ownedEnumeration, node, ctx, triples);
479
+ }
480
+
481
+ private mapAnnotationProperty(property: AnnotationProperty, ctx: MappingContext, triples: Quad[]): void {
482
+ const iri = this.elementIri(property, ctx);
483
+ if (!iri) return;
484
+ const node = namedNode(iri);
485
+ triples.push(this.quadWithGraph(node, namedNode(RDF.type), namedNode(OWL.AnnotationProperty)));
486
+ this.mapAnnotations(node, property.ownedAnnotations, ctx, triples);
487
+ this.applySpecializations(property.ownedSpecializations, node, ctx, triples, true);
488
+ this.applyPropertyEquivalences(property.ownedEquivalences, node, ctx, triples);
489
+ }
490
+
491
+ private mapScalarProperty(property: ScalarProperty, ctx: MappingContext, triples: Quad[]): void {
492
+ const iri = this.elementIri(property, ctx);
493
+ if (!iri) return;
494
+ const node = namedNode(iri);
495
+ triples.push(this.quadWithGraph(node, namedNode(RDF.type), namedNode(OWL.DatatypeProperty)));
496
+ this.mapAnnotations(node, property.ownedAnnotations, ctx, triples);
497
+ this.applyDomains(node, property.domains, ctx, triples);
498
+ this.applyRanges(node, property.ranges, ctx, triples);
499
+ if (property.functional) {
500
+ triples.push(this.quadWithGraph(node, namedNode(RDF.type), namedNode(OWL.FunctionalProperty)));
501
+ }
502
+ this.applySpecializations(property.ownedSpecializations, node, ctx, triples, true);
503
+ this.applyPropertyEquivalences(property.ownedEquivalences, node, ctx, triples);
504
+ }
505
+
506
+ private mapConceptInstance(instance: ConceptInstance, ctx: MappingContext, triples: Quad[]): void {
507
+ const iri = this.elementIri(instance, ctx);
508
+ if (!iri) return;
509
+ const node = namedNode(iri);
510
+ const isDefinition = !(instance as any).ref;
511
+
512
+ instance.ownedTypes?.forEach((typeAssertion) => this.mapTypeAssertion(node, typeAssertion, ctx, triples));
513
+ if (isDefinition) {
514
+ triples.push(this.quadWithGraph(node, namedNode(OML.type), namedNode(OML.ConceptInstance)));
515
+ }
516
+ this.mapAnnotations(node, instance.ownedAnnotations, ctx, triples);
517
+ instance.ownedPropertyValues?.forEach((pv) => this.mapPropertyValueAssertion(node, pv, ctx, triples));
518
+ }
519
+
520
+ private mapRelationInstance(instance: RelationInstance, ctx: MappingContext, triples: Quad[]): void {
521
+ const iri = this.elementIri(instance, ctx);
522
+ if (!iri) return;
523
+ const node = namedNode(iri);
524
+ const isDefinition = !(instance as any).ref;
525
+
526
+ instance.ownedTypes?.forEach((typeAssertion) => this.mapTypeAssertion(node, typeAssertion, ctx, triples));
527
+ if (isDefinition) {
528
+ triples.push(this.quadWithGraph(node, namedNode(OML.type), namedNode(OML.RelationInstance)));
529
+ }
530
+ this.mapAnnotations(node, instance.ownedAnnotations, ctx, triples);
531
+
532
+ instance.sources?.forEach((src) => {
533
+ const srcIri = this.resolveIri(src, ctx);
534
+ if (srcIri) {
535
+ triples.push(this.quadWithGraph(node, namedNode(OML.hasSource), namedNode(srcIri)));
536
+ }
537
+ });
538
+ instance.targets?.forEach((tgt) => {
539
+ const tgtIri = this.resolveIri(tgt, ctx);
540
+ if (tgtIri) {
541
+ triples.push(this.quadWithGraph(node, namedNode(OML.hasTarget), namedNode(tgtIri)));
542
+ }
543
+ });
544
+
545
+ instance.ownedPropertyValues?.forEach((pv) => this.mapPropertyValueAssertion(node, pv, ctx, triples));
546
+ }
547
+
548
+ private mapRule(rule: Rule, ctx: MappingContext, triples: Quad[]): void {
549
+ if (this.options.emitSwrlRules === false) return;
550
+ if (rule.ref) return;
551
+ const iri = this.elementIri(rule, ctx);
552
+ if (!iri) return;
553
+ const node = namedNode(iri);
554
+
555
+ triples.push(this.quadWithGraph(node, namedNode(RDF.type), namedNode(SWRL.Imp)));
556
+ triples.push(this.quadWithGraph(node, namedNode(OML.type), literal(OML.Rule)));
557
+ triples.push(this.quadWithGraph(node, namedNode(SWRL.body), this.createRdfList(ctx, this.mapRulePredicates(rule.antecedent, ctx, triples, iri, 'body'), triples, `rule-body|${iri}`)));
558
+ triples.push(this.quadWithGraph(node, namedNode(SWRL.head), this.createRdfList(ctx, this.mapRulePredicates(rule.consequent, ctx, triples, iri, 'head'), triples, `rule-head|${iri}`)));
559
+
560
+ this.mapAnnotations(node, rule.ownedAnnotations, ctx, triples);
561
+ }
562
+
563
+ private mapBuiltIn(builtIn: BuiltIn, ctx: MappingContext, triples: Quad[]): void {
564
+ const iri = this.elementIri(builtIn, ctx);
565
+ if (!iri) return;
566
+ const node = namedNode(iri);
567
+ triples.push(this.quadWithGraph(node, namedNode(RDF.type), namedNode(OML.BuiltIn)));
568
+ this.mapAnnotations(node, builtIn.ownedAnnotations, ctx, triples);
569
+ }
570
+
571
+ private mapRelationEntityForwardRule(
572
+ relationEntityIri: string,
573
+ forwardIri: string,
574
+ ctx: MappingContext,
575
+ triples: Quad[],
576
+ ): void {
577
+ const relationVar = this.toSwrlVariable('r', triples);
578
+ const sourceVar = this.toSwrlVariable('s', triples);
579
+ const targetVar = this.toSwrlVariable('t', triples);
580
+
581
+ const classAtom = skolemize(ctx.namespace, 'rule-atom', relationEntityIri, 'relationEntity', 'class');
582
+ triples.push(this.quadWithGraph(classAtom, namedNode(RDF.type), namedNode(SWRL.ClassAtom)));
583
+ triples.push(this.quadWithGraph(classAtom, namedNode(SWRL.classPredicate), namedNode(relationEntityIri)));
584
+ triples.push(this.quadWithGraph(classAtom, namedNode(SWRL.argument1), relationVar));
585
+
586
+ const sourceAtom = skolemize(ctx.namespace, 'rule-atom', relationEntityIri, 'relationEntity', 'source');
587
+ triples.push(this.quadWithGraph(sourceAtom, namedNode(RDF.type), namedNode(SWRL.IndividualPropertyAtom)));
588
+ triples.push(this.quadWithGraph(sourceAtom, namedNode(SWRL.propertyPredicate), namedNode(OML.hasSource)));
589
+ triples.push(this.quadWithGraph(sourceAtom, namedNode(SWRL.argument1), relationVar));
590
+ triples.push(this.quadWithGraph(sourceAtom, namedNode(SWRL.argument2), sourceVar));
591
+
592
+ const targetAtom = skolemize(ctx.namespace, 'rule-atom', relationEntityIri, 'relationEntity', 'target');
593
+ triples.push(this.quadWithGraph(targetAtom, namedNode(RDF.type), namedNode(SWRL.IndividualPropertyAtom)));
594
+ triples.push(this.quadWithGraph(targetAtom, namedNode(SWRL.propertyPredicate), namedNode(OML.hasTarget)));
595
+ triples.push(this.quadWithGraph(targetAtom, namedNode(SWRL.argument1), relationVar));
596
+ triples.push(this.quadWithGraph(targetAtom, namedNode(SWRL.argument2), targetVar));
597
+
598
+ const headAtom = skolemize(ctx.namespace, 'rule-atom', relationEntityIri, 'relationEntity', 'forward');
599
+ triples.push(this.quadWithGraph(headAtom, namedNode(RDF.type), namedNode(SWRL.IndividualPropertyAtom)));
600
+ triples.push(this.quadWithGraph(headAtom, namedNode(SWRL.propertyPredicate), namedNode(forwardIri)));
601
+ triples.push(this.quadWithGraph(headAtom, namedNode(SWRL.argument1), sourceVar));
602
+ triples.push(this.quadWithGraph(headAtom, namedNode(SWRL.argument2), targetVar));
603
+
604
+ const body = this.createSwrlAtomList(ctx, [classAtom, sourceAtom, targetAtom], triples, `relation-entity-rule-body|${relationEntityIri}`);
605
+ const head = this.createSwrlAtomList(ctx, [headAtom], triples, `relation-entity-rule-head|${relationEntityIri}`);
606
+ const ruleNode = namedNode(`${forwardIri}__derivation`);
607
+ triples.push(this.quadWithGraph(ruleNode, namedNode(RDF.type), namedNode(SWRL.Imp)));
608
+ triples.push(this.quadWithGraph(ruleNode, namedNode(SWRL.body), body));
609
+ triples.push(this.quadWithGraph(ruleNode, namedNode(SWRL.head), head));
610
+ }
611
+
612
+ private mapRulePredicates(
613
+ predicates: Predicate[],
614
+ ctx: MappingContext,
615
+ triples: Quad[],
616
+ ruleIri: string,
617
+ side: 'body' | 'head',
618
+ ): Quad_Object[] {
619
+ return predicates.flatMap((predicate, index) => this.mapRulePredicate(predicate, ctx, triples, ruleIri, side, index));
620
+ }
621
+
622
+ private mapRulePredicate(
623
+ predicate: Predicate,
624
+ ctx: MappingContext,
625
+ triples: Quad[],
626
+ ruleIri: string,
627
+ side: 'body' | 'head',
628
+ index: number,
629
+ ): Quad_Object[] {
630
+ const atomSeed = `${ruleIri}|${side}|${index}`;
631
+ if (isTypePredicate(predicate)) {
632
+ const typeIri = this.resolveIri(predicate.type, ctx);
633
+ if (!typeIri) return [];
634
+
635
+ if (predicate.type.ref && isScalar(predicate.type.ref)) {
636
+ const argument = this.toSwrlDArgument(predicate.argument, ctx, triples);
637
+ if (!argument) return [];
638
+ const atom = skolemize(ctx.namespace, 'rule-atom', atomSeed, 'type', 'dataRange', typeIri, this.termKey(argument));
639
+ triples.push(this.quadWithGraph(atom, namedNode(RDF.type), namedNode(SWRL.DataRangeAtom)));
640
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.dataRange), namedNode(typeIri)));
641
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.argument1), argument));
642
+ return [atom];
643
+ }
644
+
645
+ const argument = this.toSwrlIArgument(predicate.argument, ctx, triples);
646
+ if (!argument) return [];
647
+ const atom = skolemize(ctx.namespace, 'rule-atom', atomSeed, 'type', 'class', typeIri, this.termKey(argument));
648
+ triples.push(this.quadWithGraph(atom, namedNode(RDF.type), namedNode(SWRL.ClassAtom)));
649
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.classPredicate), namedNode(typeIri)));
650
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.argument1), argument));
651
+ return [atom];
652
+ }
653
+
654
+ if (isRelationEntityPredicate(predicate)) {
655
+ const typeIri = this.resolveIri(predicate.type, ctx);
656
+ const argument = this.toSwrlIArgument(predicate.argument, ctx, triples);
657
+ const argument1 = this.toSwrlIArgument(predicate.argument1, ctx, triples);
658
+ const argument2 = this.toSwrlIArgument(predicate.argument2, ctx, triples);
659
+ if (!typeIri || !argument || !argument1 || !argument2) return [];
660
+
661
+ const typeAtom = skolemize(ctx.namespace, 'rule-atom', atomSeed, 'relationEntity', 'type', typeIri, this.termKey(argument));
662
+ triples.push(this.quadWithGraph(typeAtom, namedNode(RDF.type), namedNode(SWRL.ClassAtom)));
663
+ triples.push(this.quadWithGraph(typeAtom, namedNode(SWRL.classPredicate), namedNode(typeIri)));
664
+ triples.push(this.quadWithGraph(typeAtom, namedNode(SWRL.argument1), argument));
665
+
666
+ const sourceAtom = skolemize(ctx.namespace, 'rule-atom', atomSeed, 'relationEntity', 'source', this.termKey(argument), this.termKey(argument1));
667
+ triples.push(this.quadWithGraph(sourceAtom, namedNode(RDF.type), namedNode(SWRL.IndividualPropertyAtom)));
668
+ triples.push(this.quadWithGraph(sourceAtom, namedNode(SWRL.propertyPredicate), namedNode(OML.hasSource)));
669
+ triples.push(this.quadWithGraph(sourceAtom, namedNode(SWRL.argument1), argument));
670
+ triples.push(this.quadWithGraph(sourceAtom, namedNode(SWRL.argument2), argument1));
671
+
672
+ const targetAtom = skolemize(ctx.namespace, 'rule-atom', atomSeed, 'relationEntity', 'target', this.termKey(argument), this.termKey(argument2));
673
+ triples.push(this.quadWithGraph(targetAtom, namedNode(RDF.type), namedNode(SWRL.IndividualPropertyAtom)));
674
+ triples.push(this.quadWithGraph(targetAtom, namedNode(SWRL.propertyPredicate), namedNode(OML.hasTarget)));
675
+ triples.push(this.quadWithGraph(targetAtom, namedNode(SWRL.argument1), argument));
676
+ triples.push(this.quadWithGraph(targetAtom, namedNode(SWRL.argument2), argument2));
677
+
678
+ return [typeAtom, sourceAtom, targetAtom];
679
+ }
680
+
681
+ if (isPropertyPredicate(predicate)) {
682
+ const propertyIri = this.resolveIri(predicate.property, ctx);
683
+ const argument1 = this.toSwrlIArgument(predicate.argument1, ctx, triples);
684
+ if (!propertyIri || !argument1) return [];
685
+
686
+ const isDataPredicate =
687
+ (predicate.property.ref && isScalarProperty(predicate.property.ref)) ||
688
+ (predicate.property.ref && isAnnotationProperty(predicate.property.ref) && Boolean(predicate.argument2.literal));
689
+ const atom = isDataPredicate
690
+ ? skolemize(ctx.namespace, 'rule-atom', atomSeed, 'property', 'data', propertyIri, this.termKey(argument1))
691
+ : skolemize(ctx.namespace, 'rule-atom', atomSeed, 'property', 'object', propertyIri, this.termKey(argument1));
692
+ if (isDataPredicate) {
693
+ const argument2 = this.toSwrlDArgument(predicate.argument2, ctx, triples);
694
+ if (!argument2) return [];
695
+ triples.push(this.quadWithGraph(atom, namedNode(RDF.type), namedNode(SWRL.DatavaluedPropertyAtom)));
696
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.propertyPredicate), namedNode(propertyIri)));
697
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.argument1), argument1));
698
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.argument2), argument2));
699
+ } else {
700
+ const argument2 = this.toSwrlIArgument(predicate.argument2, ctx, triples);
701
+ if (!argument2) return [];
702
+ triples.push(this.quadWithGraph(atom, namedNode(RDF.type), namedNode(SWRL.IndividualPropertyAtom)));
703
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.propertyPredicate), namedNode(propertyIri)));
704
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.argument1), argument1));
705
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.argument2), argument2));
706
+ }
707
+ return [atom];
708
+ }
709
+
710
+ if (isSameAsPredicate(predicate)) {
711
+ const argument1 = this.toSwrlIArgument(predicate.argument1, ctx, triples);
712
+ const argument2 = this.toSwrlIArgument(predicate.argument2, ctx, triples);
713
+ if (!argument1 || !argument2) return [];
714
+ const atom = skolemize(ctx.namespace, 'rule-atom', atomSeed, 'sameAs', this.termKey(argument1), this.termKey(argument2));
715
+ triples.push(this.quadWithGraph(atom, namedNode(RDF.type), namedNode(SWRL.SameIndividualAtom)));
716
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.argument1), argument1));
717
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.argument2), argument2));
718
+ return [atom];
719
+ }
720
+
721
+ if (isDifferentFromPredicate(predicate)) {
722
+ const argument1 = this.toSwrlIArgument(predicate.argument1, ctx, triples);
723
+ const argument2 = this.toSwrlIArgument(predicate.argument2, ctx, triples);
724
+ if (!argument1 || !argument2) return [];
725
+ const atom = skolemize(ctx.namespace, 'rule-atom', atomSeed, 'differentFrom', this.termKey(argument1), this.termKey(argument2));
726
+ triples.push(this.quadWithGraph(atom, namedNode(RDF.type), namedNode(SWRL.DifferentIndividualsAtom)));
727
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.argument1), argument1));
728
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.argument2), argument2));
729
+ return [atom];
730
+ }
731
+
732
+ if (isBuiltInPredicate(predicate)) {
733
+ const builtInIri = this.resolveIri(predicate.builtIn, ctx);
734
+ if (!builtInIri) return [];
735
+ const argumentsList = predicate.arguments
736
+ .map((argument) => this.toSwrlDArgument(argument, ctx, triples))
737
+ .filter((argument): argument is Quad_Object => Boolean(argument));
738
+ const atom = skolemize(ctx.namespace, 'rule-atom', atomSeed, 'builtin', builtInIri, ...argumentsList.map((argument) => this.termKey(argument)));
739
+ triples.push(this.quadWithGraph(atom, namedNode(RDF.type), namedNode(SWRL.BuiltinAtom)));
740
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.builtin), namedNode(builtInIri)));
741
+ triples.push(this.quadWithGraph(atom, namedNode(SWRL.arguments), this.createRdfList(ctx, argumentsList, triples, `rule-builtin-args|${atomSeed}|${builtInIri}`)));
742
+ return [atom];
743
+ }
744
+
745
+ return [];
746
+ }
747
+
748
+ private toSwrlIArgument(argument: Argument, ctx: MappingContext, triples: Quad[]): Quad_Object | undefined {
749
+ if (argument.variable) {
750
+ return this.toSwrlVariable(argument.variable, triples);
751
+ }
752
+ const instanceIri = this.resolveIri(argument.instance, ctx);
753
+ if (!instanceIri) return undefined;
754
+ return namedNode(instanceIri);
755
+ }
756
+
757
+ private toSwrlDArgument(argument: Argument, ctx: MappingContext, triples: Quad[]): Quad_Object | undefined {
758
+ if (argument.variable) {
759
+ return this.toSwrlVariable(argument.variable, triples);
760
+ }
761
+ if (argument.literal) {
762
+ return this.toLiteral(argument.literal, ctx);
763
+ }
764
+ return undefined;
765
+ }
766
+
767
+ private toSwrlVariable(variable: string, triples: Quad[]): Quad_Object {
768
+ const node = namedNode(`urn:swrl:var#${variable}`);
769
+ triples.push(this.quadWithGraph(node, namedNode(RDF.type), namedNode(SWRL.Variable)));
770
+ return node;
771
+ }
772
+
773
+ private mapTypeAssertion(subject: ReturnType<typeof namedNode>, assertion: TypeAssertion, ctx: MappingContext, triples: Quad[]): void {
774
+ const typeIri = this.resolveIri(assertion.type, ctx);
775
+ if (typeIri) {
776
+ triples.push(this.quadWithGraph(subject, namedNode(RDF.type), namedNode(typeIri)));
777
+ }
778
+ }
779
+
780
+ private mapPropertyValueAssertion(
781
+ subject: TermNode,
782
+ assertion: PropertyValueAssertion,
783
+ ctx: MappingContext,
784
+ triples: Quad[],
785
+ ): void {
786
+ const propertyIri = this.resolveIri(assertion.property, ctx);
787
+ if (!propertyIri) return;
788
+ const propertyNode = namedNode(propertyIri);
789
+
790
+ assertion.literalValues?.forEach((lit) => {
791
+ const litNode = this.toLiteral(lit, ctx);
792
+ if (litNode) {
793
+ triples.push(this.quadWithGraph(subject, propertyNode, litNode));
794
+ }
795
+ });
796
+
797
+ assertion.referencedValues?.forEach((ref) => {
798
+ const objIri = this.resolveIri(ref, ctx);
799
+ if (objIri) {
800
+ triples.push(this.quadWithGraph(subject, propertyNode, namedNode(objIri)));
801
+ }
802
+ });
803
+
804
+ assertion.containedValues?.forEach((contained, index) => {
805
+ const valueNode = skolemize(ctx.namespace, 'anon', this.termKey(subject), propertyIri, String(index));
806
+ triples.push(this.quadWithGraph(subject, propertyNode, valueNode));
807
+ this.mapAnonymousInstance(contained, valueNode, ctx, triples, subject);
808
+ });
809
+
810
+ }
811
+
812
+ private mapAnnotations(
813
+ subject: TermNode,
814
+ annotations: Annotation[] | undefined,
815
+ ctx: MappingContext,
816
+ triples: Quad[],
817
+ ): void {
818
+ annotations?.forEach((annotation) => {
819
+ const propertyIri = this.resolveIri(annotation.property, ctx);
820
+ if (!propertyIri) return;
821
+ const propertyNode = namedNode(propertyIri);
822
+ annotation.literalValues?.forEach((lit) => {
823
+ const litNode = this.toLiteral(lit, ctx);
824
+ if (litNode) {
825
+ triples.push(this.quadWithGraph(subject, propertyNode, litNode));
826
+ }
827
+ });
828
+ annotation.referencedValues?.forEach((ref) => {
829
+ const objIri = this.resolveIri(ref, ctx);
830
+ if (objIri) {
831
+ triples.push(this.quadWithGraph(subject, propertyNode, namedNode(objIri)));
832
+ }
833
+ });
834
+ });
835
+ }
836
+
837
+ private mapAnonymousInstance(
838
+ instance: AnonymousInstance,
839
+ node: ReturnType<typeof namedNode>,
840
+ ctx: MappingContext,
841
+ triples: Quad[],
842
+ source?: TermNode,
843
+ ): void {
844
+ if (isAnonymousConceptInstance(instance)) {
845
+ if (instance.type) {
846
+ const typeIri = this.resolveIri(instance.type, ctx);
847
+ if (typeIri) {
848
+ triples.push(this.quadWithGraph(node, namedNode(RDF.type), namedNode(typeIri)));
849
+ }
850
+ }
851
+ triples.push(this.quadWithGraph(node, namedNode(OML.type), namedNode(OML.ConceptInstance)));
852
+ instance.ownedPropertyValues?.forEach((pv, index) => this.mapPropertyValueAssertion(node, pv, ctx, triples));
853
+ } else if (isAnonymousRelationInstance(instance)) {
854
+ if (source) {
855
+ triples.push(this.quadWithGraph(node, namedNode(OML.hasSource), source));
856
+ }
857
+ const targetIri = this.resolveIri(instance.target, ctx);
858
+ if (targetIri) {
859
+ triples.push(this.quadWithGraph(node, namedNode(OML.hasTarget), namedNode(targetIri)));
860
+ }
861
+ triples.push(this.quadWithGraph(node, namedNode(OML.type), namedNode(OML.RelationInstance)));
862
+ instance.ownedPropertyValues?.forEach((pv, index) => this.mapPropertyValueAssertion(node, pv, ctx, triples));
863
+ }
864
+ }
865
+
866
+ private applySpecializations(
867
+ axioms: SpecializationAxiom[] | undefined,
868
+ subNode: ReturnType<typeof namedNode>,
869
+ ctx: MappingContext,
870
+ triples: Quad[],
871
+ isProperty = false,
872
+ ): void {
873
+ axioms?.forEach((ax) => {
874
+ const superIri = this.resolveIri(ax.superTerm, ctx);
875
+ if (superIri) {
876
+ triples.push(
877
+ this.quadWithGraph(subNode, namedNode(isProperty ? RDFS.subPropertyOf : RDFS.subClassOf), namedNode(superIri)),
878
+ );
879
+ }
880
+ });
881
+ }
882
+
883
+ private applyEquivalences(
884
+ axioms: EntityEquivalenceAxiom[] | undefined,
885
+ classNode: ReturnType<typeof namedNode>,
886
+ ctx: MappingContext,
887
+ triples: Quad[],
888
+ ): void {
889
+ axioms?.forEach((ax) => {
890
+ ax.superTerms?.forEach((sup) => {
891
+ const superIri = this.resolveIri(sup, ctx);
892
+ if (superIri) {
893
+ triples.push(this.quadWithGraph(classNode, namedNode(OWL.equivalentClass), namedNode(superIri)));
894
+ }
895
+ });
896
+ this.applyPropertyRestrictions(ax.ownedPropertyRestrictions, classNode, ctx, triples);
897
+ });
898
+ }
899
+
900
+ private applyKeys(
901
+ axioms: KeyAxiom[] | undefined,
902
+ classNode: ReturnType<typeof namedNode>,
903
+ ctx: MappingContext,
904
+ triples: Quad[],
905
+ ): void {
906
+ axioms?.forEach((ax) => {
907
+ const propertyNodes = ax.properties
908
+ .map((property) => this.resolveIri(property, ctx))
909
+ .filter((iri): iri is string => Boolean(iri))
910
+ .map((iri) => namedNode(iri));
911
+ if (!propertyNodes.length) return;
912
+ const listHead = this.createRdfList(ctx, propertyNodes, triples, `keys|${classNode.value}|${propertyNodes.map((node) => node.value).join('|')}`);
913
+ triples.push(this.quadWithGraph(classNode, namedNode(OWL.hasKey), listHead));
914
+ });
915
+ }
916
+
917
+ private applyScalarEquivalences(
918
+ axioms: ScalarEquivalenceAxiom[] | undefined,
919
+ scalarNode: ReturnType<typeof namedNode>,
920
+ ctx: MappingContext,
921
+ triples: Quad[],
922
+ ): void {
923
+ axioms?.forEach((ax) => {
924
+ ax.superTerms?.forEach((sup) => {
925
+ const superIri = this.resolveIri(sup, ctx);
926
+ if (superIri) {
927
+ triples.push(this.quadWithGraph(scalarNode, namedNode(OWL.equivalentClass), namedNode(superIri)));
928
+ }
929
+ });
930
+
931
+ this.createScalarFacetRestrictionNodes(ax, ctx, triples).forEach((restrictionNode) => {
932
+ triples.push(this.quadWithGraph(scalarNode, namedNode(OWL.equivalentClass), restrictionNode));
933
+ });
934
+ });
935
+ }
936
+
937
+ private applyInstanceEnumeration(
938
+ enumeration: InstanceEnumerationAxiom | undefined,
939
+ classNode: ReturnType<typeof namedNode>,
940
+ ctx: MappingContext,
941
+ triples: Quad[],
942
+ ): void {
943
+ const instances = enumeration?.instances ?? [];
944
+ if (!instances.length) return;
945
+ const instanceNodes = instances
946
+ .map((instance) => this.resolveIri(instance, ctx))
947
+ .filter((iri): iri is string => Boolean(iri))
948
+ .map((iri) => namedNode(iri));
949
+ if (!instanceNodes.length) return;
950
+ const listHead = this.createRdfList(ctx, instanceNodes, triples, `instance-enum|${classNode.value}|${instanceNodes.map((node) => node.value).join('|')}`);
951
+ triples.push(this.quadWithGraph(classNode, namedNode(OWL.oneOf), listHead));
952
+ }
953
+
954
+ private applyScalarEnumeration(
955
+ enumeration: LiteralEnumerationAxiom | undefined,
956
+ scalarNode: ReturnType<typeof namedNode>,
957
+ ctx: MappingContext,
958
+ triples: Quad[],
959
+ ): void {
960
+ const literals = enumeration?.literals ?? [];
961
+ if (!literals.length) return;
962
+ const literalNodes = literals
963
+ .map((lit) => this.toLiteral(lit, ctx))
964
+ .filter((node): node is Quad_Object => Boolean(node));
965
+ if (!literalNodes.length) return;
966
+ const literalSignature = literalNodes.map((node) => this.termKey(node)).join('|');
967
+ const listHead = this.createRdfList(ctx, literalNodes, triples, `scalar-enum|${scalarNode.value}|${literalSignature}`);
968
+ const dataRangeNode = skolemize(ctx.namespace, 'datatype-enum', scalarNode.value, literalSignature);
969
+ triples.push(this.quadWithGraph(dataRangeNode, namedNode(RDF.type), namedNode(RDFS.Datatype)));
970
+ triples.push(this.quadWithGraph(dataRangeNode, namedNode(OWL.oneOf), listHead));
971
+ triples.push(this.quadWithGraph(scalarNode, namedNode(OWL.equivalentClass), dataRangeNode));
972
+ }
973
+
974
+ private applyPropertyEquivalences(
975
+ axioms: PropertyEquivalenceAxiom[] | undefined,
976
+ propertyNode: ReturnType<typeof namedNode>,
977
+ ctx: MappingContext,
978
+ triples: Quad[],
979
+ ): void {
980
+ axioms?.forEach((ax) => {
981
+ ax.superTerms?.forEach((sup) => {
982
+ const superIri = this.resolveIri(sup, ctx);
983
+ if (superIri) {
984
+ triples.push(this.quadWithGraph(propertyNode, namedNode(OWL.equivalentProperty), namedNode(superIri)));
985
+ }
986
+ });
987
+ });
988
+ }
989
+
990
+ private applyPropertyRestrictions(
991
+ axioms: PropertyRestrictionAxiom[] | undefined,
992
+ classNode: ReturnType<typeof namedNode>,
993
+ ctx: MappingContext,
994
+ triples: Quad[],
995
+ ): void {
996
+ axioms?.forEach((ax) => {
997
+ const restrictionNode = this.mapRestriction(ax, ctx, triples);
998
+ if (restrictionNode) {
999
+ triples.push(this.quadWithGraph(classNode, namedNode(RDFS.subClassOf), restrictionNode));
1000
+ }
1001
+ });
1002
+ }
1003
+
1004
+ private createScalarFacetRestrictionNodes(
1005
+ axiom: ScalarEquivalenceAxiom,
1006
+ ctx: MappingContext,
1007
+ triples: Quad[],
1008
+ ): Array<ReturnType<typeof namedNode>> {
1009
+ const facets: Array<{ iri: string; value: Quad_Object }> = [];
1010
+
1011
+ axiom.length.forEach((value) => {
1012
+ facets.push({ iri: XSD.length, value: literal(String(value), namedNode(XSD.integer)) });
1013
+ });
1014
+ axiom.minLength.forEach((value) => {
1015
+ facets.push({ iri: XSD.minLength, value: literal(String(value), namedNode(XSD.integer)) });
1016
+ });
1017
+ axiom.maxLength.forEach((value) => {
1018
+ facets.push({ iri: XSD.maxLength, value: literal(String(value), namedNode(XSD.integer)) });
1019
+ });
1020
+ axiom.pattern.forEach((value) => {
1021
+ facets.push({ iri: XSD.pattern, value: literal(value) });
1022
+ });
1023
+ axiom.language.forEach((value) => {
1024
+ facets.push({ iri: RDF.langRange, value: literal(value) });
1025
+ });
1026
+ axiom.minInclusive.forEach((value) => {
1027
+ const node = this.toLiteral(value, ctx);
1028
+ if (node) facets.push({ iri: XSD.minInclusive, value: node });
1029
+ });
1030
+ axiom.minExclusive.forEach((value) => {
1031
+ const node = this.toLiteral(value, ctx);
1032
+ if (node) facets.push({ iri: XSD.minExclusive, value: node });
1033
+ });
1034
+ axiom.maxInclusive.forEach((value) => {
1035
+ const node = this.toLiteral(value, ctx);
1036
+ if (node) facets.push({ iri: XSD.maxInclusive, value: node });
1037
+ });
1038
+ axiom.maxExclusive.forEach((value) => {
1039
+ const node = this.toLiteral(value, ctx);
1040
+ if (node) facets.push({ iri: XSD.maxExclusive, value: node });
1041
+ });
1042
+
1043
+ if (!facets.length) return [];
1044
+
1045
+ const datatypes = axiom.superTerms
1046
+ .map((sup) => this.resolveIri(sup, ctx))
1047
+ .filter((iri): iri is string => Boolean(iri));
1048
+
1049
+ if (!datatypes.length) {
1050
+ if (axiom.language.length > 0) {
1051
+ datatypes.push(RDF.langString);
1052
+ } else if (axiom.length.length || axiom.minLength.length || axiom.maxLength.length || axiom.pattern.length) {
1053
+ datatypes.push(XSD.string);
1054
+ } else {
1055
+ const lexicalFacet = facets.find((facet) => facet.value.termType === 'Literal');
1056
+ if (lexicalFacet && lexicalFacet.value.termType === 'Literal') {
1057
+ datatypes.push(lexicalFacet.value.datatype.value);
1058
+ }
1059
+ }
1060
+ }
1061
+
1062
+ return datatypes.map((datatypeIri) => {
1063
+ const facetSignature = facets.map((facet) => `${facet.iri}=${this.termKey(facet.value)}`).join('|');
1064
+ const restrictionNode = skolemize(ctx.namespace, 'restriction', 'datatype', datatypeIri, facetSignature);
1065
+ triples.push(this.quadWithGraph(restrictionNode, namedNode(OWL.onDatatype), namedNode(datatypeIri)));
1066
+ const restrictionItems = facets.map((facet, index) => {
1067
+ const facetNode = skolemize(ctx.namespace, 'restriction-facet', datatypeIri, String(index), facet.iri, this.termKey(facet.value));
1068
+ triples.push(this.quadWithGraph(facetNode, namedNode(facet.iri), facet.value));
1069
+ return facetNode;
1070
+ });
1071
+ const listHead = this.createRdfList(ctx, restrictionItems, triples, `restriction-facets|${datatypeIri}|${facetSignature}`);
1072
+ triples.push(this.quadWithGraph(restrictionNode, namedNode(OWL.withRestrictions), listHead));
1073
+ return restrictionNode;
1074
+ });
1075
+ }
1076
+
1077
+ private mapRestriction(
1078
+ axiom: PropertyRestrictionAxiom,
1079
+ ctx: MappingContext,
1080
+ triples: Quad[],
1081
+ ): ReturnType<typeof namedNode> | undefined {
1082
+ if (isPropertyRangeRestrictionAxiom(axiom)) {
1083
+ return this.mapRangeRestriction(axiom, ctx, triples);
1084
+ }
1085
+ if (isPropertyCardinalityRestrictionAxiom(axiom)) {
1086
+ return this.mapCardinalityRestriction(axiom, ctx, triples);
1087
+ }
1088
+ if (isPropertyValueRestrictionAxiom(axiom)) {
1089
+ return this.mapValueRestriction(axiom, ctx, triples);
1090
+ }
1091
+ if (isPropertySelfRestrictionAxiom(axiom)) {
1092
+ return this.mapSelfRestriction(axiom, ctx, triples);
1093
+ }
1094
+ return undefined;
1095
+ }
1096
+
1097
+ private mapRangeRestriction(
1098
+ axiom: PropertyRangeRestrictionAxiom,
1099
+ ctx: MappingContext,
1100
+ triples: Quad[],
1101
+ ): ReturnType<typeof namedNode> | undefined {
1102
+ const propertyIri = this.resolveIri(axiom.property, ctx);
1103
+ const rangeIri = this.resolveIri(axiom.range, ctx);
1104
+ if (!propertyIri || !rangeIri) return undefined;
1105
+ const node = skolemize(ctx.namespace, 'restriction', propertyIri, axiom.kind, rangeIri, 'range');
1106
+
1107
+ triples.push(this.quadWithGraph(node, namedNode(RDF.type), namedNode(OWL.Restriction)));
1108
+ triples.push(this.quadWithGraph(node, namedNode(OWL.onProperty), namedNode(propertyIri)));
1109
+ const predicate = axiom.kind === 'all' ? OWL.allValuesFrom : OWL.someValuesFrom;
1110
+ triples.push(this.quadWithGraph(node, namedNode(predicate), namedNode(rangeIri)));
1111
+ return node;
1112
+ }
1113
+
1114
+ private mapCardinalityRestriction(
1115
+ axiom: PropertyCardinalityRestrictionAxiom,
1116
+ ctx: MappingContext,
1117
+ triples: Quad[],
1118
+ ): ReturnType<typeof namedNode> | undefined {
1119
+ const propertyIri = this.resolveIri(axiom.property, ctx);
1120
+ if (!propertyIri) return undefined;
1121
+ const resolvedProperty = (axiom.property as any)?.ref as SemanticProperty | undefined;
1122
+ const rangeIri = this.resolveIri(axiom.range, ctx) ?? '';
1123
+ const node = skolemize(ctx.namespace, 'restriction', propertyIri, axiom.kind, String(axiom.cardinality), rangeIri);
1124
+ triples.push(this.quadWithGraph(node, namedNode(RDF.type), namedNode(OWL.Restriction)));
1125
+ triples.push(this.quadWithGraph(node, namedNode(OWL.onProperty), namedNode(propertyIri)));
1126
+ if (rangeIri) {
1127
+ const on = resolvedProperty && isScalarProperty(resolvedProperty) ? OWL.onDataRange : OWL.onClass;
1128
+ triples.push(this.quadWithGraph(node, namedNode(on), namedNode(rangeIri)));
1129
+ }
1130
+ const cardPredicate =
1131
+ axiom.kind === 'min'
1132
+ ? OWL.minCardinality
1133
+ : axiom.kind === 'max'
1134
+ ? OWL.maxCardinality
1135
+ : OWL.cardinality;
1136
+ triples.push(this.quadWithGraph(node, namedNode(cardPredicate), literal(String(axiom.cardinality), namedNode(XSD.integer))));
1137
+ return node;
1138
+ }
1139
+
1140
+ private mapValueRestriction(
1141
+ axiom: PropertyValueRestrictionAxiom,
1142
+ ctx: MappingContext,
1143
+ triples: Quad[],
1144
+ ): ReturnType<typeof namedNode> | undefined {
1145
+ const propertyIri = this.resolveIri(axiom.property, ctx);
1146
+ if (!propertyIri) return undefined;
1147
+ const valueSeed = axiom.literalValue
1148
+ ? this.literalKey(axiom.literalValue, ctx)
1149
+ : axiom.referencedValue
1150
+ ? this.resolveIri(axiom.referencedValue, ctx) ?? ''
1151
+ : 'contained';
1152
+ const node = skolemize(ctx.namespace, 'restriction', propertyIri, 'hasValue', valueSeed);
1153
+ triples.push(this.quadWithGraph(node, namedNode(RDF.type), namedNode(OWL.Restriction)));
1154
+ triples.push(this.quadWithGraph(node, namedNode(OWL.onProperty), namedNode(propertyIri)));
1155
+
1156
+ if (axiom.literalValue) {
1157
+ const litNode = this.toLiteral(axiom.literalValue, ctx);
1158
+ if (litNode) {
1159
+ triples.push(this.quadWithGraph(node, namedNode(OWL.hasValue), litNode));
1160
+ }
1161
+ } else if (axiom.referencedValue) {
1162
+ const refIri = this.resolveIri(axiom.referencedValue, ctx);
1163
+ if (refIri) {
1164
+ triples.push(this.quadWithGraph(node, namedNode(OWL.hasValue), namedNode(refIri)));
1165
+ }
1166
+ } else if (axiom.containedValue) {
1167
+ const valueNode = skolemize(ctx.namespace, 'anon', propertyIri, 'hasValue');
1168
+ triples.push(this.quadWithGraph(node, namedNode(OWL.hasValue), valueNode));
1169
+ this.mapAnonymousInstance(axiom.containedValue, valueNode, ctx, triples);
1170
+ }
1171
+ return node;
1172
+ }
1173
+
1174
+ private mapSelfRestriction(
1175
+ axiom: PropertySelfRestrictionAxiom,
1176
+ ctx: MappingContext,
1177
+ triples: Quad[],
1178
+ ): ReturnType<typeof namedNode> | undefined {
1179
+ const propertyIri = this.resolveIri(axiom.property, ctx);
1180
+ if (!propertyIri) return undefined;
1181
+ const node = skolemize(ctx.namespace, 'restriction', propertyIri, 'hasSelf');
1182
+ triples.push(this.quadWithGraph(node, namedNode(RDF.type), namedNode(OWL.Restriction)));
1183
+ triples.push(this.quadWithGraph(node, namedNode(OWL.onProperty), namedNode(propertyIri)));
1184
+ triples.push(this.quadWithGraph(node, namedNode(OWL.hasSelf), literal('true', namedNode(XSD.boolean))));
1185
+ return node;
1186
+ }
1187
+
1188
+ private applyDomainRange(
1189
+ propertyNode: ReturnType<typeof namedNode>,
1190
+ domains: Array<unknown> | undefined,
1191
+ ranges: Array<unknown> | undefined,
1192
+ ctx: MappingContext,
1193
+ triples: Quad[],
1194
+ ): void {
1195
+ this.applyDomains(propertyNode, domains, ctx, triples);
1196
+ this.applyRanges(propertyNode, ranges, ctx, triples);
1197
+ }
1198
+
1199
+ private applyDomains(
1200
+ propertyNode: ReturnType<typeof namedNode>,
1201
+ domains: Array<unknown> | undefined,
1202
+ ctx: MappingContext,
1203
+ triples: Quad[],
1204
+ ): void {
1205
+ domains?.forEach((d) => {
1206
+ const iri = this.resolveIri(d, ctx);
1207
+ if (iri) {
1208
+ triples.push(this.quadWithGraph(propertyNode, namedNode(RDFS.domain), namedNode(iri)));
1209
+ }
1210
+ });
1211
+ }
1212
+
1213
+ private applyRanges(
1214
+ propertyNode: ReturnType<typeof namedNode>,
1215
+ ranges: Array<unknown> | undefined,
1216
+ ctx: MappingContext,
1217
+ triples: Quad[],
1218
+ ): void {
1219
+ ranges?.forEach((r) => {
1220
+ const iri = this.resolveIri(r, ctx);
1221
+ if (iri) {
1222
+ triples.push(this.quadWithGraph(propertyNode, namedNode(RDFS.range), namedNode(iri)));
1223
+ }
1224
+ });
1225
+ }
1226
+
1227
+ private applyObjectPropertyCharacteristics(
1228
+ propertyNode: ReturnType<typeof namedNode>,
1229
+ relation: RelationBase,
1230
+ triples: Quad[],
1231
+ ): void {
1232
+ if (relation.functional) {
1233
+ triples.push(this.quadWithGraph(propertyNode, namedNode(RDF.type), namedNode(OWL.FunctionalProperty)));
1234
+ }
1235
+ if (relation.inverseFunctional) {
1236
+ triples.push(this.quadWithGraph(propertyNode, namedNode(RDF.type), namedNode(OWL.InverseFunctionalProperty)));
1237
+ }
1238
+ if (relation.symmetric) {
1239
+ triples.push(this.quadWithGraph(propertyNode, namedNode(RDF.type), namedNode(OWL.SymmetricProperty)));
1240
+ }
1241
+ if (relation.asymmetric) {
1242
+ triples.push(this.quadWithGraph(propertyNode, namedNode(RDF.type), namedNode(OWL.AsymmetricProperty)));
1243
+ }
1244
+ if (relation.reflexive) {
1245
+ triples.push(this.quadWithGraph(propertyNode, namedNode(RDF.type), namedNode(OWL.ReflexiveProperty)));
1246
+ }
1247
+ if (relation.irreflexive) {
1248
+ triples.push(this.quadWithGraph(propertyNode, namedNode(RDF.type), namedNode(OWL.IrreflexiveProperty)));
1249
+ }
1250
+ if (relation.transitive) {
1251
+ triples.push(this.quadWithGraph(propertyNode, namedNode(RDF.type), namedNode(OWL.TransitiveProperty)));
1252
+ }
1253
+ }
1254
+
1255
+ private quadWithGraph(subject: Quad_Subject, predicate: Quad_Predicate, object: Quad_Object): Quad {
1256
+ return quad(subject, predicate, object);
1257
+ }
1258
+
1259
+ private createRdfList(
1260
+ ctx: MappingContext,
1261
+ items: Quad_Object[],
1262
+ triples: Quad[],
1263
+ listSeed: string,
1264
+ ): ReturnType<typeof namedNode> {
1265
+ if (!items.length) {
1266
+ return namedNode(RDF.nil);
1267
+ }
1268
+ const base = `${listSeed}|${items.map((item) => this.termKey(item)).join('|')}`;
1269
+ const head = skolemize(ctx.namespace, 'list', base, '0');
1270
+ let current = head;
1271
+ items.forEach((item, index) => {
1272
+ triples.push(this.quadWithGraph(current, namedNode(RDF.first), item));
1273
+ if (index === items.length - 1) {
1274
+ triples.push(this.quadWithGraph(current, namedNode(RDF.rest), namedNode(RDF.nil)));
1275
+ } else {
1276
+ const next = skolemize(ctx.namespace, 'list', base, String(index + 1));
1277
+ triples.push(this.quadWithGraph(current, namedNode(RDF.rest), next));
1278
+ current = next;
1279
+ }
1280
+ });
1281
+ return head;
1282
+ }
1283
+
1284
+ private createSwrlAtomList(
1285
+ ctx: MappingContext,
1286
+ items: Quad_Object[],
1287
+ triples: Quad[],
1288
+ listSeed: string,
1289
+ ): ReturnType<typeof namedNode> {
1290
+ const head = this.createRdfList(ctx, items, triples, listSeed);
1291
+ if (head.value === RDF.nil) {
1292
+ return head;
1293
+ }
1294
+ let current = head;
1295
+ while (current.value !== RDF.nil) {
1296
+ triples.push(this.quadWithGraph(current, namedNode(RDF.type), namedNode(SWRL.AtomList)));
1297
+ const next = triples.find(
1298
+ (quad) => quad.subject.termType === 'NamedNode'
1299
+ && quad.subject.value === current.value
1300
+ && quad.predicate.value === RDF.rest
1301
+ && quad.object.termType === 'NamedNode',
1302
+ )?.object;
1303
+ if (!next || next.termType !== 'NamedNode') {
1304
+ break;
1305
+ }
1306
+ current = next;
1307
+ }
1308
+ return head;
1309
+ }
1310
+
1311
+ private createContext(ontology: Ontology): MappingContext {
1312
+ const namespace = this.normalizeNamespace((ontology as any).namespace ?? '');
1313
+ const prefix = (ontology as any).prefix ?? '';
1314
+ return {
1315
+ ontologyIri: namespace.replace(/[\/#]+$/, ''),
1316
+ namespace,
1317
+ prefix,
1318
+ prefixes: this.buildPrefixMap(ontology),
1319
+ };
1320
+ }
1321
+
1322
+ private buildPrefixMap(ontology: Ontology): PrefixMap {
1323
+ const map: PrefixMap = {};
1324
+ const ns = this.normalizeNamespace((ontology as any).namespace ?? '');
1325
+ const prefix = (ontology as any).prefix;
1326
+ if (prefix) {
1327
+ map[prefix] = ns;
1328
+ }
1329
+ ontology.ownedImports?.forEach((imp: Import) => {
1330
+ const imported = imp.imported?.ref as Ontology | undefined;
1331
+ const importedNs = imported ? this.normalizeNamespace((imported as any).namespace ?? '') : undefined;
1332
+ const importedPrefix = imp.prefix ?? (imported as any)?.prefix;
1333
+ if (importedPrefix && importedNs) {
1334
+ map[importedPrefix] = importedNs;
1335
+ }
1336
+ });
1337
+ return map;
1338
+ }
1339
+
1340
+ private ontologyTypeIri(ontology: Ontology): string {
1341
+ if (isVocabulary(ontology)) return OML.Vocabulary;
1342
+ if (isVocabularyBundle(ontology)) return OML.VocabularyBundle;
1343
+ if (isDescription(ontology)) return OML.Description;
1344
+ if (isDescriptionBundle(ontology)) return OML.DescriptionBundle;
1345
+ return OML.Vocabulary;
1346
+ }
1347
+
1348
+ private importedOntologyIri(imp: Import, ctx: MappingContext): string | undefined {
1349
+ if (imp.imported?.ref && isOntology(imp.imported.ref)) {
1350
+ return this.normalizeNamespace((imp.imported.ref as any).namespace ?? '').replace(/[\/#]+$/, '');
1351
+ }
1352
+ const refText = (imp.imported as any)?.$refText ?? (imp.imported as any)?.refText;
1353
+ if (refText) {
1354
+ return this.resolveFromRefText(refText, ctx)?.replace(/[\/#]+$/, '');
1355
+ }
1356
+ return undefined;
1357
+ }
1358
+
1359
+ private getForwardIri(base: RelationBase, ctx: MappingContext): string {
1360
+ if (isRelationEntity(base)) {
1361
+ if (base.forwardRelation?.name) {
1362
+ const ont = this.getOntology(base);
1363
+ const ns = this.normalizeNamespace((ont as any)?.namespace ?? ctx.namespace);
1364
+ return `${ns}${base.forwardRelation.name}`;
1365
+ }
1366
+ const name = ((base.ref as any)?.name ?? base.name ?? '').replace(/^\^/, '');
1367
+ return `${ctx.namespace}has${this.toFirstUpper(name)}Forward`;
1368
+ }
1369
+ return this.elementIri(base, ctx) ?? '';
1370
+ }
1371
+
1372
+ private elementIri(element: { name?: string; namespace?: string; $container?: any; ref?: any }, ctx: MappingContext): string | undefined {
1373
+ if (!element) return undefined;
1374
+ // If this is a ref wrapper, resolve to the referenced element's IRI.
1375
+ if ((element as any).ref?.ref) {
1376
+ return this.elementIri((element as any).ref.ref as any, ctx);
1377
+ }
1378
+ const name = (element as any).name ?? (element as any).ref?.name;
1379
+ if (!name) return undefined;
1380
+ const ontology = this.getOntology(element);
1381
+ const namespace = ontology ? this.normalizeNamespace((ontology as any).namespace ?? ctx.namespace) : ctx.namespace;
1382
+ return `${namespace}${name.replace(/^\^/, '')}`;
1383
+ }
1384
+
1385
+ private getOntology(element: any): Ontology | undefined {
1386
+ let current: any = element;
1387
+ while (current && !isOntology(current)) {
1388
+ current = current.$container;
1389
+ }
1390
+ return current as Ontology | undefined;
1391
+ }
1392
+
1393
+ private resolveIri(ref: any, ctx: MappingContext): string | undefined {
1394
+ if (!ref) return undefined;
1395
+ if (typeof ref === 'string') {
1396
+ return this.resolveFromRefText(ref, ctx);
1397
+ }
1398
+ if (ref.ref && (ref.ref as any).name) {
1399
+ return this.elementIri(ref.ref as any, ctx);
1400
+ }
1401
+ if (ref.name) {
1402
+ return this.elementIri(ref, ctx);
1403
+ }
1404
+ const refText = ref.$refText ?? ref.refText;
1405
+ if (refText) {
1406
+ return this.resolveFromRefText(refText, ctx);
1407
+ }
1408
+ return undefined;
1409
+ }
1410
+
1411
+ private resolveFromRefText(refText: string, ctx: MappingContext): string | undefined {
1412
+ if (refText.startsWith('<') && refText.endsWith('>')) {
1413
+ return refText.slice(1, -1);
1414
+ }
1415
+ const parts = refText.split(':');
1416
+ if (parts.length === 2) {
1417
+ const [prefix, local] = parts;
1418
+ const ns = ctx.prefixes[prefix];
1419
+ if (ns) {
1420
+ return `${ns}${local}`;
1421
+ }
1422
+ }
1423
+ return undefined;
1424
+ }
1425
+
1426
+ private normalizeNamespace(ns: string): string {
1427
+ return ns.replace(/^<|>$/g, '');
1428
+ }
1429
+
1430
+ private termKey(term: Quad_Object): string {
1431
+ if (term.termType === 'NamedNode') {
1432
+ return `iri:${term.value}`;
1433
+ }
1434
+ if (term.termType === 'Literal') {
1435
+ return `lit:${term.value}@${term.language}^^${term.datatype.value}`;
1436
+ }
1437
+ return `${term.termType}:${term.value}`;
1438
+ }
1439
+
1440
+ private literalKey(value: Literal, ctx: MappingContext): string {
1441
+ const term = this.toLiteral(value, ctx);
1442
+ return term ? this.termKey(term) : '';
1443
+ }
1444
+
1445
+ private toLiteral(value: Literal, ctx: MappingContext): Quad_Object | undefined {
1446
+ if (isBooleanLiteral(value)) {
1447
+ return literal(String(value.value), namedNode(XSD.boolean));
1448
+ }
1449
+ if (isIntegerLiteral(value)) {
1450
+ return literal(String(value.value), namedNode(XSD.integer));
1451
+ }
1452
+ if (isDecimalLiteral(value)) {
1453
+ return literal(String(value.value), namedNode(XSD.decimal));
1454
+ }
1455
+ if (isDoubleLiteral(value)) {
1456
+ return literal(String(value.value), namedNode(XSD.double));
1457
+ }
1458
+ if (isQuotedLiteral(value)) {
1459
+ if (value.type) {
1460
+ const dt = this.resolveIri(value.type, ctx);
1461
+ return literal(value.value, dt ? namedNode(dt) : undefined);
1462
+ }
1463
+ if (value.langTag) {
1464
+ return literal(value.value, value.langTag);
1465
+ }
1466
+ return literal(value.value);
1467
+ }
1468
+ return undefined;
1469
+ }
1470
+
1471
+ private toFirstUpper(name: string): string {
1472
+ if (!name) return name;
1473
+ if (name.length === 1) return name.toUpperCase();
1474
+ return `${name[0].toUpperCase()}${name.slice(1)}`;
1475
+ }
1476
+
1477
+ private deduplicateQuads(quads: ReadonlyArray<Quad>): Quad[] {
1478
+ const unique = new Map<string, Quad>();
1479
+ for (const quad of quads) {
1480
+ const key = `${quad.subject.id}|${quad.predicate.id}|${quad.object.id}|${quad.graph.id}`;
1481
+ if (!unique.has(key)) {
1482
+ unique.set(key, quad);
1483
+ }
1484
+ }
1485
+ return [...unique.values()];
1486
+ }
1487
+
1488
+ }
1489
+
1490
+ export function createOwlOntologyQuads(): Quad[] {
1491
+ const triples: Quad[] = [];
1492
+ const ontologyNode = namedNode(OWL_ONTOLOGY_IRI);
1493
+ triples.push(quad(ontologyNode, namedNode(RDF.type), namedNode(OWL.Ontology)));
1494
+ triples.push(quad(ontologyNode, namedNode(OML.type), namedNode(OML.Vocabulary)));
1495
+ triples.push(quad(ontologyNode, namedNode(OML.namespace), namedNode(OWL_ONTOLOGY_NAMESPACE)));
1496
+ triples.push(quad(ontologyNode, namedNode(OML.prefix), literal(OWL_ONTOLOGY_PREFIX)));
1497
+ for (const term of OML_TERMS) {
1498
+ triples.push(quad(namedNode(term.iri), namedNode(RDF.type), namedNode(term.rdfType)));
1499
+ }
1500
+ return triples;
1501
+ }
1502
+
1503
+ export function owlOntologyPrefixes(): Record<string, string> {
1504
+ return {
1505
+ oml: OWL_ONTOLOGY_NAMESPACE,
1506
+ rdf: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
1507
+ rdfs: 'http://www.w3.org/2000/01/rdf-schema#',
1508
+ owl: 'http://www.w3.org/2002/07/owl#',
1509
+ };
1510
+ }