@oml/language 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 (91) hide show
  1. package/README.md +44 -0
  2. package/out/oml/generated/ast.d.ts +2109 -0
  3. package/out/oml/generated/ast.js +1807 -0
  4. package/out/oml/generated/ast.js.map +1 -0
  5. package/out/oml/generated/grammar.d.ts +6 -0
  6. package/out/oml/generated/grammar.js +6885 -0
  7. package/out/oml/generated/grammar.js.map +1 -0
  8. package/out/oml/generated/module.d.ts +13 -0
  9. package/out/oml/generated/module.js +21 -0
  10. package/out/oml/generated/module.js.map +1 -0
  11. package/out/oml/index.d.ts +17 -0
  12. package/out/oml/index.js +19 -0
  13. package/out/oml/index.js.map +1 -0
  14. package/out/oml/oml-candidates.d.ts +27 -0
  15. package/out/oml/oml-candidates.js +146 -0
  16. package/out/oml/oml-candidates.js.map +1 -0
  17. package/out/oml/oml-code-actions.d.ts +6 -0
  18. package/out/oml/oml-code-actions.js +79 -0
  19. package/out/oml/oml-code-actions.js.map +1 -0
  20. package/out/oml/oml-completion.d.ts +50 -0
  21. package/out/oml/oml-completion.js +188 -0
  22. package/out/oml/oml-completion.js.map +1 -0
  23. package/out/oml/oml-converter.d.ts +10 -0
  24. package/out/oml/oml-converter.js +62 -0
  25. package/out/oml/oml-converter.js.map +1 -0
  26. package/out/oml/oml-document-validator.d.ts +10 -0
  27. package/out/oml/oml-document-validator.js +31 -0
  28. package/out/oml/oml-document-validator.js.map +1 -0
  29. package/out/oml/oml-document.d.ts +9 -0
  30. package/out/oml/oml-document.js +18 -0
  31. package/out/oml/oml-document.js.map +1 -0
  32. package/out/oml/oml-edit.d.ts +72 -0
  33. package/out/oml/oml-edit.js +1155 -0
  34. package/out/oml/oml-edit.js.map +1 -0
  35. package/out/oml/oml-formatter.d.ts +22 -0
  36. package/out/oml/oml-formatter.js +357 -0
  37. package/out/oml/oml-formatter.js.map +1 -0
  38. package/out/oml/oml-hover.d.ts +13 -0
  39. package/out/oml/oml-hover.js +71 -0
  40. package/out/oml/oml-hover.js.map +1 -0
  41. package/out/oml/oml-index-manager.d.ts +10 -0
  42. package/out/oml/oml-index-manager.js +48 -0
  43. package/out/oml/oml-index-manager.js.map +1 -0
  44. package/out/oml/oml-index.d.ts +20 -0
  45. package/out/oml/oml-index.js +133 -0
  46. package/out/oml/oml-index.js.map +1 -0
  47. package/out/oml/oml-module.d.ts +42 -0
  48. package/out/oml/oml-module.js +76 -0
  49. package/out/oml/oml-module.js.map +1 -0
  50. package/out/oml/oml-rename.d.ts +14 -0
  51. package/out/oml/oml-rename.js +114 -0
  52. package/out/oml/oml-rename.js.map +1 -0
  53. package/out/oml/oml-scope.d.ts +30 -0
  54. package/out/oml/oml-scope.js +225 -0
  55. package/out/oml/oml-scope.js.map +1 -0
  56. package/out/oml/oml-serializer.d.ts +2 -0
  57. package/out/oml/oml-serializer.js +883 -0
  58. package/out/oml/oml-serializer.js.map +1 -0
  59. package/out/oml/oml-utils.d.ts +53 -0
  60. package/out/oml/oml-utils.js +241 -0
  61. package/out/oml/oml-utils.js.map +1 -0
  62. package/out/oml/oml-validator.d.ts +49 -0
  63. package/out/oml/oml-validator.js +668 -0
  64. package/out/oml/oml-validator.js.map +1 -0
  65. package/out/oml/oml-workspace.d.ts +23 -0
  66. package/out/oml/oml-workspace.js +68 -0
  67. package/out/oml/oml-workspace.js.map +1 -0
  68. package/package.json +50 -0
  69. package/src/oml/generated/ast.ts +2641 -0
  70. package/src/oml/generated/grammar.ts +6887 -0
  71. package/src/oml/generated/module.ts +25 -0
  72. package/src/oml/index.ts +19 -0
  73. package/src/oml/oml-candidates.ts +176 -0
  74. package/src/oml/oml-code-actions.ts +120 -0
  75. package/src/oml/oml-completion.ts +222 -0
  76. package/src/oml/oml-converter.ts +66 -0
  77. package/src/oml/oml-document-validator.ts +39 -0
  78. package/src/oml/oml-document.ts +24 -0
  79. package/src/oml/oml-edit.ts +1292 -0
  80. package/src/oml/oml-formatter.ts +390 -0
  81. package/src/oml/oml-hover.ts +93 -0
  82. package/src/oml/oml-index-manager.ts +56 -0
  83. package/src/oml/oml-index.ts +145 -0
  84. package/src/oml/oml-module.ts +105 -0
  85. package/src/oml/oml-rename.ts +140 -0
  86. package/src/oml/oml-scope.ts +279 -0
  87. package/src/oml/oml-serializer.ts +1080 -0
  88. package/src/oml/oml-utils.ts +294 -0
  89. package/src/oml/oml-validator.ts +725 -0
  90. package/src/oml/oml-workspace.ts +81 -0
  91. package/src/oml/oml.langium +594 -0
@@ -0,0 +1,1080 @@
1
+ // Copyright (c) 2026 Modelware. All rights reserved.
2
+
3
+ import type {
4
+ Annotation,
5
+ AnnotationProperty,
6
+ AnonymousInstance,
7
+ Argument,
8
+ Aspect,
9
+ BuiltIn,
10
+ BuiltInPredicate,
11
+ Concept,
12
+ Description,
13
+ DescriptionBundle,
14
+ DescriptionStatement,
15
+ DifferentFromPredicate,
16
+ EntityEquivalenceAxiom,
17
+ ForwardRelation,
18
+ Import,
19
+ InstanceEnumerationAxiom,
20
+ KeyAxiom,
21
+ Literal,
22
+ LiteralEnumerationAxiom,
23
+ NamedInstance,
24
+ Ontology,
25
+ Predicate,
26
+ PropertyCardinalityRestrictionAxiom,
27
+ PropertyEquivalenceAxiom,
28
+ PropertyPredicate,
29
+ PropertyRangeRestrictionAxiom,
30
+ PropertyRestrictionAxiom,
31
+ PropertySelfRestrictionAxiom,
32
+ PropertyValueAssertion,
33
+ PropertyValueRestrictionAxiom,
34
+ QuotedLiteral,
35
+ RelationEntity,
36
+ RelationEntityPredicate,
37
+ ReverseRelation,
38
+ Rule,
39
+ SameAsPredicate,
40
+ Scalar,
41
+ ScalarEquivalenceAxiom,
42
+ ScalarProperty,
43
+ SpecializableTerm,
44
+ SpecializationAxiom,
45
+ TypeAssertion,
46
+ TypePredicate,
47
+ UnreifiedRelation,
48
+ Vocabulary,
49
+ VocabularyBundle,
50
+ VocabularyStatement,
51
+ } from './generated/ast.js';
52
+ import {
53
+ isAnnotationProperty,
54
+ isAnonymousConceptInstance,
55
+ isAnonymousRelationInstance,
56
+ isAspect,
57
+ isBooleanLiteral,
58
+ isBuiltIn,
59
+ isBuiltInPredicate,
60
+ isConcept,
61
+ isConceptInstance,
62
+ isDecimalLiteral,
63
+ isDescription,
64
+ isDescriptionBundle,
65
+ isDifferentFromPredicate,
66
+ isDoubleLiteral,
67
+ isForwardRelation,
68
+ isIntegerLiteral,
69
+ isPropertyCardinalityRestrictionAxiom,
70
+ isPropertyPredicate,
71
+ isPropertyRangeRestrictionAxiom,
72
+ isPropertySelfRestrictionAxiom,
73
+ isPropertyValueRestrictionAxiom,
74
+ isQuotedLiteral,
75
+ isRelationEntity,
76
+ isRelationEntityPredicate,
77
+ isRelationInstance,
78
+ isReverseRelation,
79
+ isRule,
80
+ isSameAsPredicate,
81
+ isScalar,
82
+ isScalarProperty,
83
+ isSpecializableTerm,
84
+ isTypePredicate,
85
+ isUnreifiedRelation,
86
+ isVocabulary,
87
+ isVocabularyBundle,
88
+ } from './generated/ast.js';
89
+ import {
90
+ findOwningOntologyNode,
91
+ normalizeNamespace,
92
+ resolveImportNamespace,
93
+ splitIri
94
+ } from './oml-utils.js';
95
+
96
+ const INDENT = ' ';
97
+ type SerializeContext = {
98
+ namespace: string;
99
+ prefix?: string;
100
+ prefixByNamespace: Map<string, string>;
101
+ };
102
+ let activeContext: SerializeContext | null = null;
103
+
104
+ export const serializeOntology = (ontology: Ontology): string => {
105
+ const prev = activeContext;
106
+ activeContext = createSerializeContext(ontology);
107
+ try {
108
+ if (isDescription(ontology)) {
109
+ return serializeDescription(ontology);
110
+ }
111
+ if (isDescriptionBundle(ontology)) {
112
+ return serializeDescriptionBundle(ontology);
113
+ }
114
+ if (isVocabulary(ontology)) {
115
+ return serializeVocabulary(ontology);
116
+ }
117
+ if (isVocabularyBundle(ontology)) {
118
+ return serializeVocabularyBundle(ontology);
119
+ }
120
+ throw new Error('Serializer only supports OML ontologies for now.');
121
+ } finally {
122
+ activeContext = prev;
123
+ }
124
+ };
125
+
126
+ const serializeVocabulary = (vocabulary: Vocabulary): string => {
127
+ const lines: string[] = [];
128
+ pushAnnotations(lines, '', vocabulary.ownedAnnotations);
129
+
130
+ const namespace = wrapNamespace(vocabulary.namespace);
131
+ lines.push(`vocabulary ${namespace} as ${serializeName(vocabulary.prefix)} {`);
132
+
133
+ if (vocabulary.ownedImports?.length) {
134
+ for (const imp of vocabulary.ownedImports) {
135
+ lines.push(`${INDENT}${serializeImport(imp)}`);
136
+ }
137
+ }
138
+
139
+ if (vocabulary.ownedStatements?.length) {
140
+ if (vocabulary.ownedImports?.length) {
141
+ lines.push('');
142
+ }
143
+ for (const [index, statement] of vocabulary.ownedStatements.entries()) {
144
+ if (index > 0) {
145
+ lines.push('');
146
+ }
147
+ lines.push(serializeVocabularyStatement(statement, INDENT));
148
+ }
149
+ }
150
+
151
+ lines.push('}');
152
+ return `${lines.join('\n')}\n`;
153
+ };
154
+
155
+ const serializeVocabularyBundle = (vocabulary: VocabularyBundle): string => {
156
+ const lines: string[] = [];
157
+ pushAnnotations(lines, '', vocabulary.ownedAnnotations);
158
+
159
+ const namespace = wrapNamespace(vocabulary.namespace);
160
+ lines.push(`vocabulary bundle ${namespace} as ${serializeName(vocabulary.prefix)} {`);
161
+
162
+ if (vocabulary.ownedImports?.length) {
163
+ for (const imp of vocabulary.ownedImports) {
164
+ lines.push(`${INDENT}${serializeImport(imp)}`);
165
+ }
166
+ }
167
+
168
+ lines.push('}');
169
+ return `${lines.join('\n')}\n`;
170
+ };
171
+
172
+ const serializeDescription = (description: Description): string => {
173
+ const lines: string[] = [];
174
+ pushAnnotations(lines, '', description.ownedAnnotations);
175
+
176
+ const namespace = wrapNamespace(description.namespace);
177
+ lines.push(`description ${namespace} as ${serializeName(description.prefix)} {`);
178
+
179
+ if (description.ownedImports?.length) {
180
+ for (const imp of description.ownedImports) {
181
+ lines.push(`${INDENT}${serializeImport(imp)}`);
182
+ }
183
+ }
184
+
185
+ if (description.ownedStatements?.length) {
186
+ if (description.ownedImports?.length) {
187
+ lines.push('');
188
+ }
189
+ for (const [index, statement] of description.ownedStatements.entries()) {
190
+ if (index > 0) {
191
+ lines.push('');
192
+ }
193
+ lines.push(serializeDescriptionStatement(statement, INDENT));
194
+ }
195
+ }
196
+
197
+ lines.push('}');
198
+ return `${lines.join('\n')}\n`;
199
+ };
200
+
201
+ const serializeDescriptionBundle = (description: DescriptionBundle): string => {
202
+ const lines: string[] = [];
203
+ pushAnnotations(lines, '', description.ownedAnnotations);
204
+
205
+ const namespace = wrapNamespace(description.namespace);
206
+ lines.push(`description bundle ${namespace} as ${serializeName(description.prefix)} {`);
207
+
208
+ if (description.ownedImports?.length) {
209
+ for (const imp of description.ownedImports) {
210
+ lines.push(`${INDENT}${serializeImport(imp)}`);
211
+ }
212
+ }
213
+
214
+ lines.push('}');
215
+ return `${lines.join('\n')}\n`;
216
+ };
217
+
218
+ const serializeVocabularyStatement = (statement: VocabularyStatement, indent: string): string => {
219
+ if (isRule(statement)) {
220
+ return serializeRule(statement, indent);
221
+ }
222
+ if (isBuiltIn(statement)) {
223
+ return serializeBuiltIn(statement, indent);
224
+ }
225
+ if (isSpecializableTerm(statement)) {
226
+ return serializeSpecializableTerm(statement, indent);
227
+ }
228
+ return '';
229
+ };
230
+
231
+ const serializeDescriptionStatement = (statement: DescriptionStatement, indent: string): string => {
232
+ return serializeNamedInstance(statement, indent);
233
+ };
234
+
235
+ const serializeImport = (imp: Import): string => {
236
+ const namespace = resolveImportNamespace(imp);
237
+ const prefix = imp.prefix ? ` as ${serializeName(imp.prefix)}` : '';
238
+ return `${imp.kind} ${wrapNamespace(namespace)}${prefix}`;
239
+ };
240
+
241
+ const serializeRule = (rule: Rule, indent: string): string => {
242
+ const lines: string[] = [];
243
+ pushAnnotations(lines, indent, rule.ownedAnnotations);
244
+
245
+ const header = rule.ref?.$refText
246
+ ? `ref rule ${rule.ref.$refText}`
247
+ : `rule ${serializeName(rule.name)}`.trim();
248
+ const predicates = serializeRulePredicates(rule);
249
+ const body = predicates ? `${header} [${predicates}]` : header;
250
+ lines.push(`${indent}${body}`);
251
+ return lines.join('\n');
252
+ };
253
+
254
+ const serializeRulePredicates = (rule: Rule): string => {
255
+ const antecedent = (rule.antecedent ?? []).map(serializePredicate).filter(Boolean);
256
+ const consequent = (rule.consequent ?? []).map(serializePredicate).filter(Boolean);
257
+ if (!antecedent.length && !consequent.length) {
258
+ return '';
259
+ }
260
+ const antText = antecedent.join(' & ');
261
+ const conText = consequent.join(' & ');
262
+ if (antText && conText) {
263
+ return `${antText} -> ${conText}`;
264
+ }
265
+ if (antText) {
266
+ return `${antText} ->`;
267
+ }
268
+ return `-> ${conText}`;
269
+ };
270
+
271
+ const serializeBuiltIn = (builtIn: BuiltIn, indent: string): string => {
272
+ const lines: string[] = [];
273
+ pushAnnotations(lines, indent, builtIn.ownedAnnotations);
274
+ const header = builtIn.ref?.$refText
275
+ ? `ref builtin ${builtIn.ref.$refText}`
276
+ : `builtin ${serializeName(builtIn.name)}`.trim();
277
+ lines.push(`${indent}${header}`);
278
+ return lines.join('\n');
279
+ };
280
+
281
+ const serializePredicate = (predicate: Predicate): string => {
282
+ if (isTypePredicate(predicate)) {
283
+ return serializeTypePredicate(predicate);
284
+ }
285
+ if (isRelationEntityPredicate(predicate)) {
286
+ return serializeRelationEntityPredicate(predicate);
287
+ }
288
+ if (isPropertyPredicate(predicate)) {
289
+ return serializePropertyPredicate(predicate);
290
+ }
291
+ if (isSameAsPredicate(predicate)) {
292
+ return serializeSameAsPredicate(predicate);
293
+ }
294
+ if (isDifferentFromPredicate(predicate)) {
295
+ return serializeDifferentFromPredicate(predicate);
296
+ }
297
+ if (isBuiltInPredicate(predicate)) {
298
+ return serializeBuiltInPredicate(predicate);
299
+ }
300
+ return '';
301
+ };
302
+
303
+ const serializeArgument = (argument: Argument): string => {
304
+ if (argument.variable) {
305
+ return argument.variable;
306
+ }
307
+ if (argument.literal) {
308
+ return serializeLiteral(argument.literal);
309
+ }
310
+ if (argument.instance) {
311
+ return resolveRefText(argument.instance);
312
+ }
313
+ return '';
314
+ };
315
+
316
+ const serializeTypePredicate = (predicate: TypePredicate): string => {
317
+ const typeRef = resolveRefText(predicate.type);
318
+ return `${typeRef}(${serializeArgument(predicate.argument)})`;
319
+ };
320
+
321
+ const serializeRelationEntityPredicate = (predicate: RelationEntityPredicate): string => {
322
+ const typeRef = resolveRefText(predicate.type);
323
+ const arg1 = serializeArgument(predicate.argument1);
324
+ const arg = serializeArgument(predicate.argument);
325
+ const arg2 = serializeArgument(predicate.argument2);
326
+ return `${typeRef}(${arg1}, ${arg}, ${arg2})`;
327
+ };
328
+
329
+ const serializePropertyPredicate = (predicate: PropertyPredicate): string => {
330
+ const property = resolveRefText(predicate.property);
331
+ const arg1 = serializeArgument(predicate.argument1);
332
+ const arg2 = serializeArgument(predicate.argument2);
333
+ return `${property}(${arg1}, ${arg2})`;
334
+ };
335
+
336
+ const serializeSameAsPredicate = (predicate: SameAsPredicate): string => {
337
+ const arg1 = serializeArgument(predicate.argument1);
338
+ const arg2 = serializeArgument(predicate.argument2);
339
+ return `sameAs(${arg1}, ${arg2})`;
340
+ };
341
+
342
+ const serializeDifferentFromPredicate = (predicate: DifferentFromPredicate): string => {
343
+ const arg1 = serializeArgument(predicate.argument1);
344
+ const arg2 = serializeArgument(predicate.argument2);
345
+ return `differentFrom(${arg1}, ${arg2})`;
346
+ };
347
+
348
+ const serializeBuiltInPredicate = (predicate: BuiltInPredicate): string => {
349
+ const builtIn = resolveRefText(predicate.builtIn);
350
+ const args = (predicate.arguments ?? []).map(serializeArgument).filter(Boolean).join(', ');
351
+ return args ? `builtIn(${builtIn}, ${args})` : `builtIn(${builtIn})`;
352
+ };
353
+
354
+ const serializeSpecializableTerm = (term: SpecializableTerm, indent: string): string => {
355
+ if (isScalar(term)) {
356
+ return serializeScalar(term, indent);
357
+ }
358
+ if (isAspect(term)) {
359
+ return serializeAspect(term, indent);
360
+ }
361
+ if (isConcept(term)) {
362
+ return serializeConcept(term, indent);
363
+ }
364
+ if (isRelationEntity(term)) {
365
+ return serializeRelationEntity(term, indent);
366
+ }
367
+ if (isAnnotationProperty(term)) {
368
+ return serializeAnnotationProperty(term, indent);
369
+ }
370
+ if (isScalarProperty(term)) {
371
+ return serializeScalarProperty(term, indent);
372
+ }
373
+ if (isUnreifiedRelation(term)) {
374
+ return serializeUnreifiedRelation(term, indent);
375
+ }
376
+ return '';
377
+ };
378
+
379
+ const serializeAnnotationProperty = (property: AnnotationProperty, indent: string): string => {
380
+ const lines: string[] = [];
381
+ pushAnnotations(lines, indent, property.ownedAnnotations);
382
+ const header = property.ref?.$refText
383
+ ? `ref annotation property ${property.ref.$refText}`
384
+ : `annotation property ${serializeName(property.name)}`.trim();
385
+ const suffix = `${serializePropertySpecialization(property.ownedSpecializations)}${serializePropertyEquivalences(
386
+ property.ownedEquivalences
387
+ )}`;
388
+ lines.push(`${indent}${header}${suffix}`);
389
+ return lines.join('\n');
390
+ };
391
+
392
+ const serializeScalar = (scalar: Scalar, indent: string): string => {
393
+ const lines: string[] = [];
394
+ pushAnnotations(lines, indent, scalar.ownedAnnotations);
395
+ const header = scalar.ref?.$refText ? `ref scalar ${scalar.ref.$refText}` : `scalar ${serializeName(scalar.name)}`.trim();
396
+ const blockLines: string[] = [];
397
+ if (scalar.ownedEnumeration) {
398
+ blockLines.push(serializeLiteralEnumerationAxiom(scalar.ownedEnumeration));
399
+ }
400
+ const suffix = `${serializeScalarSpecialization(scalar)}${serializeScalarEquivalences(scalar.ownedEquivalences)}`;
401
+ renderBlock(lines, indent, header, blockLines, suffix);
402
+ return lines.join('\n');
403
+ };
404
+
405
+ const serializeAspect = (aspect: Aspect, indent: string): string => {
406
+ const lines: string[] = [];
407
+ pushAnnotations(lines, indent, aspect.ownedAnnotations);
408
+ const header = aspect.ref?.$refText ? `ref aspect ${aspect.ref.$refText}` : `aspect ${serializeName(aspect.name)}`.trim();
409
+ const blockLines = (aspect.ownedKeys ?? []).map(serializeKeyAxiom);
410
+ const suffix = `${serializeEntitySpecialization(aspect)}${serializeEntityEquivalences(aspect.ownedEquivalences)}`;
411
+ renderBlock(lines, indent, header, blockLines, suffix);
412
+ return lines.join('\n');
413
+ };
414
+
415
+ const serializeConcept = (concept: Concept, indent: string): string => {
416
+ const lines: string[] = [];
417
+ pushAnnotations(lines, indent, concept.ownedAnnotations);
418
+ const header = concept.ref?.$refText ? `ref concept ${concept.ref.$refText}` : `concept ${serializeName(concept.name)}`.trim();
419
+ const blockLines: string[] = [];
420
+ if (concept.ownedEnumeration) {
421
+ blockLines.push(serializeInstanceEnumerationAxiom(concept.ownedEnumeration));
422
+ }
423
+ for (const key of concept.ownedKeys ?? []) {
424
+ blockLines.push(serializeKeyAxiom(key));
425
+ }
426
+ const suffix = `${serializeEntitySpecialization(concept)}${serializeEntityEquivalences(concept.ownedEquivalences)}`;
427
+ renderBlock(lines, indent, header, blockLines, suffix);
428
+ return lines.join('\n');
429
+ };
430
+
431
+ const serializeRelationEntity = (relation: RelationEntity, indent: string): string => {
432
+ const lines: string[] = [];
433
+ pushAnnotations(lines, indent, relation.ownedAnnotations);
434
+ const header = relation.ref?.$refText
435
+ ? `ref relation entity ${relation.ref.$refText}`
436
+ : `relation entity ${serializeName(relation.name)}`.trim();
437
+
438
+ const blockLines: string[] = [];
439
+ const sources = relation.sources?.map(resolveRefText).filter(Boolean);
440
+ if (sources.length) {
441
+ blockLines.push(`from ${sources.join(', ')}`);
442
+ }
443
+ const targets = relation.targets?.map(resolveRefText).filter(Boolean);
444
+ if (targets.length) {
445
+ blockLines.push(`to ${targets.join(', ')}`);
446
+ }
447
+ if (relation.forwardRelation) {
448
+ blockLines.push(...serializeRelationLines(relation.forwardRelation));
449
+ }
450
+ if (relation.reverseRelation) {
451
+ blockLines.push(...serializeRelationLines(relation.reverseRelation));
452
+ }
453
+ blockLines.push(...serializeRelationTraitsLines(relation));
454
+ for (const key of relation.ownedKeys ?? []) {
455
+ blockLines.push(serializeKeyAxiom(key));
456
+ }
457
+
458
+ const suffix = `${serializeEntitySpecialization(relation)}${serializeEntityEquivalences(relation.ownedEquivalences)}`;
459
+ renderBlock(lines, indent, header, blockLines, suffix);
460
+ return lines.join('\n');
461
+ };
462
+
463
+ const serializeScalarProperty = (property: ScalarProperty, indent: string): string => {
464
+ const lines: string[] = [];
465
+ pushAnnotations(lines, indent, property.ownedAnnotations);
466
+ const header = property.ref?.$refText
467
+ ? `ref scalar property ${property.ref.$refText}`
468
+ : `scalar property ${serializeName(property.name)}`.trim();
469
+
470
+ const blockLines: string[] = [];
471
+ const domains = property.domains?.map(resolveRefText).filter(Boolean);
472
+ if (domains.length) {
473
+ blockLines.push(`domain ${domains.join(', ')}`);
474
+ }
475
+ const ranges = property.ranges?.map(resolveRefText).filter(Boolean);
476
+ if (ranges.length) {
477
+ blockLines.push(`range ${ranges.join(', ')}`);
478
+ }
479
+ if (property.functional) {
480
+ blockLines.push('functional');
481
+ }
482
+
483
+ const suffix = `${serializePropertySpecialization(property.ownedSpecializations)}${serializePropertyEquivalences(
484
+ property.ownedEquivalences
485
+ )}`;
486
+ renderBlock(lines, indent, header, blockLines, suffix);
487
+ return lines.join('\n');
488
+ };
489
+
490
+ const serializeUnreifiedRelation = (relation: UnreifiedRelation, indent: string): string => {
491
+ const lines: string[] = [];
492
+ pushAnnotations(lines, indent, relation.ownedAnnotations);
493
+ const header = relation.ref?.$refText
494
+ ? `ref relation ${relation.ref.$refText}`
495
+ : `relation ${serializeName(relation.name)}`.trim();
496
+
497
+ const blockLines: string[] = [];
498
+ const sources = relation.sources?.map(resolveRefText).filter(Boolean);
499
+ if (sources.length) {
500
+ blockLines.push(`from ${sources.join(', ')}`);
501
+ }
502
+ const targets = relation.targets?.map(resolveRefText).filter(Boolean);
503
+ if (targets.length) {
504
+ blockLines.push(`to ${targets.join(', ')}`);
505
+ }
506
+ if (relation.reverseRelation) {
507
+ blockLines.push(...serializeRelationLines(relation.reverseRelation));
508
+ }
509
+ blockLines.push(...serializeRelationTraitsLines(relation));
510
+
511
+ const suffix = `${serializePropertySpecialization(relation.ownedSpecializations)}${serializePropertyEquivalences(
512
+ relation.ownedEquivalences
513
+ )}`;
514
+ renderBlock(lines, indent, header, blockLines, suffix);
515
+ return lines.join('\n');
516
+ };
517
+
518
+ const serializeRelationLines = (relation: ForwardRelation | ReverseRelation): string[] => {
519
+ const lines: string[] = [];
520
+ if (isForwardRelation(relation)) {
521
+ for (const annotation of relation.ownedAnnotations ?? []) {
522
+ lines.push(serializeAnnotation(annotation));
523
+ }
524
+ lines.push(`forward ${serializeName(relation.name)}`);
525
+ return lines;
526
+ }
527
+ if (isReverseRelation(relation)) {
528
+ for (const annotation of relation.ownedAnnotations ?? []) {
529
+ lines.push(serializeAnnotation(annotation));
530
+ }
531
+ lines.push(`reverse ${serializeName(relation.name)}`);
532
+ return lines;
533
+ }
534
+ return lines;
535
+ };
536
+
537
+ const serializeRelationTraitsLines = (relation: RelationEntity | UnreifiedRelation): string[] => {
538
+ const lines: string[] = [];
539
+ if (relation.functional) {
540
+ lines.push('functional');
541
+ }
542
+ if (relation.inverseFunctional) {
543
+ lines.push('inverse functional');
544
+ }
545
+ if (relation.symmetric) {
546
+ lines.push('symmetric');
547
+ }
548
+ if (relation.asymmetric) {
549
+ lines.push('asymmetric');
550
+ }
551
+ if (relation.reflexive) {
552
+ lines.push('reflexive');
553
+ }
554
+ if (relation.irreflexive) {
555
+ lines.push('irreflexive');
556
+ }
557
+ if (relation.transitive) {
558
+ lines.push('transitive');
559
+ }
560
+ return lines;
561
+ };
562
+
563
+ const serializeInstanceEnumerationAxiom = (axiom: InstanceEnumerationAxiom): string => {
564
+ const instances = axiom.instances?.map(resolveRefText).filter(Boolean).join(', ');
565
+ return `oneOf ${instances}`.trim();
566
+ };
567
+
568
+ const serializeLiteralEnumerationAxiom = (axiom: LiteralEnumerationAxiom): string => {
569
+ const literals = axiom.literals?.map(serializeLiteral).filter(Boolean).join(', ');
570
+ return `oneOf ${literals}`.trim();
571
+ };
572
+
573
+ const serializeKeyAxiom = (axiom: KeyAxiom): string => {
574
+ const properties = axiom.properties?.map(resolveRefText).filter(Boolean).join(', ');
575
+ return `key ${properties}`.trim();
576
+ };
577
+
578
+ const serializePropertySpecialization = (specializations: SpecializationAxiom[] = []): string => {
579
+ const supers = specializations.map(serializeSpecializationAxiom).filter(Boolean);
580
+ return supers.length ? ` < ${supers.join(', ')}` : '';
581
+ };
582
+
583
+ const serializeScalarSpecialization = (scalar: Scalar): string => {
584
+ return serializePropertySpecialization(scalar.ownedSpecializations);
585
+ };
586
+
587
+ const serializeEntitySpecialization = (entity: Aspect | Concept | RelationEntity): string => {
588
+ const supers = (entity.ownedSpecializations ?? []).map(serializeSpecializationAxiom).filter(Boolean);
589
+ const restrictions = (entity.ownedPropertyRestrictions ?? []).map(serializePropertyRestrictionAxiom).filter(Boolean);
590
+ if (!supers.length && !restrictions.length) {
591
+ return '';
592
+ }
593
+ if (supers.length && restrictions.length) {
594
+ return ` < ${supers.join(', ')} [${restrictions.join(' ')}]`;
595
+ }
596
+ if (supers.length) {
597
+ return ` < ${supers.join(', ')}`;
598
+ }
599
+ return ` < [${restrictions.join(' ')}]`;
600
+ };
601
+
602
+ const serializeEntityEquivalences = (equivalences: EntityEquivalenceAxiom[] = []): string => {
603
+ const entries = equivalences.map(serializeEntityEquivalenceAxiom).filter(Boolean);
604
+ return entries.length ? ` = ${entries.join(', ')}` : '';
605
+ };
606
+
607
+ const serializePropertyEquivalences = (equivalences: PropertyEquivalenceAxiom[] = []): string => {
608
+ const entries = equivalences.map(serializePropertyEquivalenceAxiom).filter(Boolean);
609
+ return entries.length ? ` = ${entries.join(', ')}` : '';
610
+ };
611
+
612
+ const serializeScalarEquivalences = (equivalences: ScalarEquivalenceAxiom[] = []): string => {
613
+ const entries = equivalences.map(serializeScalarEquivalenceAxiom).filter(Boolean);
614
+ return entries.length ? ` = ${entries.join(', ')}` : '';
615
+ };
616
+
617
+ const serializeSpecializationAxiom = (axiom: SpecializationAxiom): string => {
618
+ return resolveRefText(axiom.superTerm);
619
+ };
620
+
621
+ const serializeEntityEquivalenceAxiom = (axiom: EntityEquivalenceAxiom): string => {
622
+ const supers = (axiom.superTerms ?? []).map(resolveRefText).filter(Boolean);
623
+ const restrictions = (axiom.ownedPropertyRestrictions ?? []).map(serializePropertyRestrictionAxiom).filter(Boolean);
624
+ if (restrictions.length) {
625
+ if (supers.length) {
626
+ return `${supers.join(' & ')} [${restrictions.join(' ')}]`;
627
+ }
628
+ return `[${restrictions.join(' ')}]`;
629
+ }
630
+ return supers.join(' & ');
631
+ };
632
+
633
+ const serializePropertyEquivalenceAxiom = (axiom: PropertyEquivalenceAxiom): string => {
634
+ const supers = (axiom.superTerms ?? []).map(resolveRefText).filter(Boolean);
635
+ return supers.join(' ');
636
+ };
637
+
638
+ const serializeScalarEquivalenceAxiom = (axiom: ScalarEquivalenceAxiom): string => {
639
+ const supers = (axiom.superTerms ?? []).map(resolveRefText).filter(Boolean).join(' ');
640
+ const facets: string[] = [];
641
+ for (const value of axiom.length ?? []) {
642
+ facets.push(`length ${value}`);
643
+ }
644
+ for (const value of axiom.minLength ?? []) {
645
+ facets.push(`minLength ${value}`);
646
+ }
647
+ for (const value of axiom.maxLength ?? []) {
648
+ facets.push(`maxLength ${value}`);
649
+ }
650
+ for (const value of axiom.pattern ?? []) {
651
+ facets.push(`pattern ${serializeStringLiteral(value)}`);
652
+ }
653
+ for (const value of axiom.language ?? []) {
654
+ facets.push(`language ${value}`);
655
+ }
656
+ for (const value of axiom.minInclusive ?? []) {
657
+ facets.push(`minInclusive ${serializeLiteral(value)}`);
658
+ }
659
+ for (const value of axiom.minExclusive ?? []) {
660
+ facets.push(`minExclusive ${serializeLiteral(value)}`);
661
+ }
662
+ for (const value of axiom.maxInclusive ?? []) {
663
+ facets.push(`maxInclusive ${serializeLiteral(value)}`);
664
+ }
665
+ for (const value of axiom.maxExclusive ?? []) {
666
+ facets.push(`maxExclusive ${serializeLiteral(value)}`);
667
+ }
668
+ const facetText = facets.length ? ` [${facets.join(' ')}]` : '';
669
+ return `${supers}${facetText}`.trim();
670
+ };
671
+
672
+ const serializePropertyRestrictionAxiom = (axiom: PropertyRestrictionAxiom): string => {
673
+ if (isPropertyRangeRestrictionAxiom(axiom)) {
674
+ return serializePropertyRangeRestrictionAxiom(axiom);
675
+ }
676
+ if (isPropertyCardinalityRestrictionAxiom(axiom)) {
677
+ return serializePropertyCardinalityRestrictionAxiom(axiom);
678
+ }
679
+ if (isPropertyValueRestrictionAxiom(axiom)) {
680
+ return serializePropertyValueRestrictionAxiom(axiom);
681
+ }
682
+ if (isPropertySelfRestrictionAxiom(axiom)) {
683
+ return serializePropertySelfRestrictionAxiom(axiom);
684
+ }
685
+ return '';
686
+ };
687
+
688
+ const serializePropertyRangeRestrictionAxiom = (axiom: PropertyRangeRestrictionAxiom): string => {
689
+ const property = resolveRefText(axiom.property);
690
+ const range = resolveRefText(axiom.range);
691
+ return `restricts ${axiom.kind} ${property} to ${range}`.trim();
692
+ };
693
+
694
+ const serializePropertyCardinalityRestrictionAxiom = (axiom: PropertyCardinalityRestrictionAxiom): string => {
695
+ const property = resolveRefText(axiom.property);
696
+ const range = axiom.range ? ` ${resolveRefText(axiom.range)}` : '';
697
+ return `restricts ${property} to ${axiom.kind} ${axiom.cardinality}${range}`.trim();
698
+ };
699
+
700
+ const serializePropertyValueRestrictionAxiom = (axiom: PropertyValueRestrictionAxiom): string => {
701
+ const property = resolveRefText(axiom.property);
702
+ const value = serializeRestrictionValue(axiom);
703
+ return `restricts ${property} to ${value}`.trim();
704
+ };
705
+
706
+ const serializeRestrictionValue = (axiom: PropertyValueRestrictionAxiom): string => {
707
+ if (axiom.literalValue) {
708
+ return serializeLiteral(axiom.literalValue);
709
+ }
710
+ if (axiom.referencedValue) {
711
+ return resolveRefText(axiom.referencedValue);
712
+ }
713
+ if (axiom.containedValue) {
714
+ return serializeAnonymousInstance(axiom.containedValue);
715
+ }
716
+ return '';
717
+ };
718
+
719
+ const serializePropertySelfRestrictionAxiom = (axiom: PropertySelfRestrictionAxiom): string => {
720
+ const property = resolveRefText(axiom.property);
721
+ return `restricts ${property} to self`.trim();
722
+ };
723
+
724
+ const serializeNamedInstance = (instance: NamedInstance, indent: string): string => {
725
+ const lines: string[] = [];
726
+ pushAnnotations(lines, indent, instance.ownedAnnotations ?? []);
727
+
728
+ const header = serializeInstanceHeader(instance);
729
+ const body = serializeInstanceBody(instance);
730
+ renderBlock(lines, indent, header, body, '');
731
+ return lines.join('\n');
732
+ };
733
+
734
+ const serializeInstanceHeader = (instance: NamedInstance): string => {
735
+ const types = instance.ownedTypes ?? [];
736
+ const typeText = types.length ? ` : ${types.map(serializeTypeAssertion).join(', ')}` : '';
737
+ if (isRelationInstance(instance)) {
738
+ if (instance.ref?.$refText) {
739
+ return `ref relation instance ${instance.ref.$refText}${typeText}`;
740
+ }
741
+ return `relation instance ${serializeName(instance.name)}${typeText}`.trim();
742
+ }
743
+ if (isConceptInstance(instance)) {
744
+ if (instance.ref?.$refText) {
745
+ return `ref instance ${instance.ref.$refText}${typeText}`;
746
+ }
747
+ return `instance ${serializeName(instance.name)}${typeText}`.trim();
748
+ }
749
+ return '';
750
+ };
751
+
752
+ const serializeTypeAssertion = (typeAssertion: TypeAssertion): string => {
753
+ const refText = (typeAssertion.type as any)?.$refText;
754
+ if (refText) {
755
+ return refText;
756
+ }
757
+ const name = (typeAssertion.type?.ref as any)?.name;
758
+ return name ?? '';
759
+ };
760
+
761
+ const serializeInstanceBody = (instance: NamedInstance): string[] => {
762
+ const lines: string[] = [];
763
+ if (isRelationInstance(instance)) {
764
+ if (instance.sources?.length) {
765
+ const sources = instance.sources.map((ref) => resolveRefText(ref)).filter(Boolean);
766
+ if (sources.length) {
767
+ lines.push(`from ${sources.join(', ')}`);
768
+ }
769
+ }
770
+ if (instance.targets?.length) {
771
+ const targets = instance.targets.map((ref) => resolveRefText(ref)).filter(Boolean);
772
+ if (targets.length) {
773
+ lines.push(`to ${targets.join(', ')}`);
774
+ }
775
+ }
776
+ }
777
+ const properties = instance.ownedPropertyValues ?? [];
778
+ for (const prop of properties) {
779
+ lines.push(serializePropertyValueAssertion(prop));
780
+ }
781
+ return lines;
782
+ };
783
+
784
+ const serializePropertyValueAssertion = (assertion: PropertyValueAssertion): string => {
785
+ const propRef = resolveRefText(assertion.property);
786
+ const values: string[] = [];
787
+ for (const lit of assertion.literalValues ?? []) {
788
+ values.push(serializeLiteral(lit));
789
+ }
790
+ for (const ref of assertion.referencedValues ?? []) {
791
+ const refText = resolveRefText(ref);
792
+ if (refText) {
793
+ values.push(refText);
794
+ }
795
+ }
796
+ for (const contained of assertion.containedValues ?? []) {
797
+ values.push(serializeAnonymousInstance(contained));
798
+ }
799
+ const valueText = values.join(', ');
800
+ return valueText ? `${propRef} ${valueText}`.trim() : propRef;
801
+ };
802
+
803
+ const serializeAnonymousInstance = (instance: AnonymousInstance): string => {
804
+ if (isAnonymousRelationInstance(instance)) {
805
+ const header = `${resolveRefText(instance.target)} [`.trim();
806
+ const lines = [header];
807
+ appendIndentedLines(lines, INDENT, (instance.ownedPropertyValues ?? []).map(serializePropertyValueAssertion));
808
+ lines.push(']');
809
+ return lines.join('\n');
810
+ }
811
+ if (isAnonymousConceptInstance(instance)) {
812
+ const typeRef = resolveRefText(instance.type);
813
+ const header = typeRef ? `: ${typeRef} [` : '[';
814
+ const lines = [header];
815
+ appendIndentedLines(lines, INDENT, (instance.ownedPropertyValues ?? []).map(serializePropertyValueAssertion));
816
+ lines.push(']');
817
+ return lines.join('\n');
818
+ }
819
+ return '';
820
+ };
821
+
822
+ const serializeAnnotation = (annotation: Annotation): string => {
823
+ const property = resolveRefText(annotation.property);
824
+ const values: string[] = [];
825
+ for (const value of annotation.literalValues ?? []) {
826
+ values.push(serializeLiteral(value));
827
+ }
828
+ for (const ref of annotation.referencedValues ?? []) {
829
+ const refText = resolveRefText(ref);
830
+ if (refText) {
831
+ values.push(refText);
832
+ }
833
+ }
834
+ if (!values.length) {
835
+ return `@${property}`;
836
+ }
837
+ return `@${property} ${values.join(', ')}`;
838
+ };
839
+
840
+ const serializeLiteral = (literal: Literal): string => {
841
+ if (isQuotedLiteral(literal)) {
842
+ return serializeQuotedLiteral(literal);
843
+ }
844
+ if (isBooleanLiteral(literal)) {
845
+ return literal.value ? 'true' : 'false';
846
+ }
847
+ if (isIntegerLiteral(literal)) {
848
+ return `${literal.value}`;
849
+ }
850
+ if (isDecimalLiteral(literal)) {
851
+ return `${literal.value}`;
852
+ }
853
+ if (isDoubleLiteral(literal)) {
854
+ return `${literal.value}`;
855
+ }
856
+ return '';
857
+ };
858
+
859
+ const serializeQuotedLiteral = (literal: QuotedLiteral): string => {
860
+ const base = serializeStringLiteral(literal.value ?? '');
861
+ if (literal.type?.$refText) {
862
+ return `${base}^^${literal.type.$refText}`;
863
+ }
864
+ if (literal.langTag) {
865
+ return `${base}$${literal.langTag}`;
866
+ }
867
+ return base;
868
+ };
869
+
870
+ const serializeStringLiteral = (value: string): string => {
871
+ const raw = value ?? '';
872
+ if (raw.includes('\n') || raw.includes('\r')) {
873
+ if (!raw.includes('"""')) {
874
+ return `"""${raw}"""`;
875
+ }
876
+ if (!raw.includes("'''")) {
877
+ return `'''${raw}'''`;
878
+ }
879
+ }
880
+ if (!raw.includes('"')) {
881
+ return `"${raw}"`;
882
+ }
883
+ if (!raw.includes("'")) {
884
+ return `'${raw}'`;
885
+ }
886
+ if (!raw.includes('"""')) {
887
+ return `"""${raw}"""`;
888
+ }
889
+ return `'''${raw}'''`;
890
+ };
891
+
892
+ const resolveRefText = (ref: any): string => {
893
+ if (!ref) {
894
+ return '';
895
+ }
896
+ if (typeof ref === 'string') {
897
+ return formatRefText(ref);
898
+ }
899
+ if (ref.$refText) {
900
+ return formatRefText(ref.$refText);
901
+ }
902
+ const target = ref.ref ?? ref._ref ?? ref;
903
+ const name = target?.name ?? '';
904
+ if (!name) {
905
+ return '';
906
+ }
907
+ const targetOntology = findOwningOntologyNode(target);
908
+ const targetNamespace = targetOntology ? normalizeNamespace(targetOntology.namespace ?? '') : '';
909
+ if (activeContext && targetNamespace) {
910
+ if (targetNamespace === activeContext.namespace) {
911
+ return escapeIdentifier(name);
912
+ }
913
+ const prefix = activeContext.prefixByNamespace.get(targetNamespace);
914
+ if (prefix) {
915
+ return `${prefix}:${name}`;
916
+ }
917
+ }
918
+ return escapeIdentifier(name);
919
+ };
920
+
921
+ const formatRefText = (value: string): string => {
922
+ if (!value) {
923
+ return value;
924
+ }
925
+ const trimmed = value.trim();
926
+ if (trimmed.startsWith('^')) {
927
+ return trimmed;
928
+ }
929
+ if (trimmed.startsWith('<') && trimmed.endsWith('>')) {
930
+ const unwrapped = trimmed.slice(1, -1);
931
+ return formatIriRef(unwrapped);
932
+ }
933
+ if (trimmed.includes('://')) {
934
+ return formatIriRef(trimmed);
935
+ }
936
+ if (activeContext?.prefix && trimmed.startsWith(`${activeContext.prefix}:`)) {
937
+ const local = trimmed.slice(activeContext.prefix.length + 1);
938
+ return escapeIdentifier(local);
939
+ }
940
+ if (trimmed.includes(':')) {
941
+ return trimmed;
942
+ }
943
+ return escapeIdentifier(trimmed);
944
+ };
945
+
946
+ const formatIriRef = (iri: string): string => {
947
+ const parts = splitIri(iri);
948
+ if (!parts?.base || !parts.fragment || !activeContext) {
949
+ return `<${iri}>`;
950
+ }
951
+ const ns = normalizeNamespace(parts.base);
952
+ if (ns === activeContext.namespace) {
953
+ return escapeIdentifier(parts.fragment);
954
+ }
955
+ const prefix = activeContext.prefixByNamespace.get(ns);
956
+ if (prefix) {
957
+ return `${prefix}:${parts.fragment}`;
958
+ }
959
+ return `<${iri}>`;
960
+ };
961
+
962
+ const escapeIdentifier = (value: string): string => {
963
+ if (!value) {
964
+ return '';
965
+ }
966
+ if (value.startsWith('^')) {
967
+ return value;
968
+ }
969
+ return OML_KEYWORDS.has(value) ? `^${value}` : value;
970
+ };
971
+
972
+ const serializeName = (value?: string): string => escapeIdentifier(value ?? '');
973
+
974
+ const createSerializeContext = (ontology: Ontology): SerializeContext => {
975
+ const namespace = normalizeNamespace(ontology.namespace ?? '');
976
+ const prefixByNamespace = new Map<string, string>();
977
+ const prefix = (ontology as any).prefix as string | undefined;
978
+ if (prefix && namespace) {
979
+ prefixByNamespace.set(namespace, prefix);
980
+ }
981
+ (ontology as any).ownedImports?.forEach((imp: Import) => {
982
+ if (!imp.prefix) return;
983
+ const ns = normalizeNamespace(resolveImportNamespace(imp));
984
+ if (ns) {
985
+ prefixByNamespace.set(ns, imp.prefix);
986
+ }
987
+ });
988
+ return { namespace, prefix, prefixByNamespace };
989
+ };
990
+
991
+ const renderBlock = (
992
+ lines: string[],
993
+ indent: string,
994
+ header: string,
995
+ blockLines: string[],
996
+ suffix: string
997
+ ): void => {
998
+ if (blockLines.length) {
999
+ lines.push(`${indent}${header} [`);
1000
+ appendIndentedLines(lines, `${indent}${INDENT}`, blockLines);
1001
+ const closing = suffix ? `${indent}]${suffix}` : `${indent}]`;
1002
+ lines.push(closing);
1003
+ } else {
1004
+ lines.push(`${indent}${header}${suffix}`);
1005
+ }
1006
+ };
1007
+
1008
+ const appendIndentedLines = (lines: string[], indent: string, contentLines: string[]): void => {
1009
+ for (const line of contentLines) {
1010
+ const parts = line.split('\n');
1011
+ for (const part of parts) {
1012
+ lines.push(`${indent}${part}`);
1013
+ }
1014
+ }
1015
+ };
1016
+
1017
+ const pushAnnotations = (lines: string[], indent: string, annotations: Annotation[] = []): void => {
1018
+ for (const annotation of annotations) {
1019
+ lines.push(`${indent}${serializeAnnotation(annotation)}`);
1020
+ }
1021
+ };
1022
+
1023
+ const stripAngles = (value: string): string => value.replace(/^<|>$/g, '');
1024
+
1025
+ const wrapNamespace = (value: string): string => `<${stripAngles(value)}>`;
1026
+
1027
+ const OML_KEYWORDS = new Set([
1028
+ 'all',
1029
+ 'annotation',
1030
+ 'as',
1031
+ 'aspect',
1032
+ 'asymmetric',
1033
+ 'builtIn',
1034
+ 'builtin',
1035
+ 'bundle',
1036
+ 'concept',
1037
+ 'description',
1038
+ 'differentFrom',
1039
+ 'domain',
1040
+ 'entity',
1041
+ 'exactly',
1042
+ 'extends',
1043
+ 'forward',
1044
+ 'from',
1045
+ 'functional',
1046
+ 'includes',
1047
+ 'instance',
1048
+ 'inverse',
1049
+ 'irreflexive',
1050
+ 'key',
1051
+ 'language',
1052
+ 'length',
1053
+ 'max',
1054
+ 'maxExclusive',
1055
+ 'maxInclusive',
1056
+ 'maxLength',
1057
+ 'min',
1058
+ 'minExclusive',
1059
+ 'minInclusive',
1060
+ 'minLength',
1061
+ 'oneOf',
1062
+ 'pattern',
1063
+ 'property',
1064
+ 'range',
1065
+ 'ref',
1066
+ 'reflexive',
1067
+ 'relation',
1068
+ 'restricts',
1069
+ 'reverse',
1070
+ 'rule',
1071
+ 'sameAs',
1072
+ 'scalar',
1073
+ 'self',
1074
+ 'some',
1075
+ 'symmetric',
1076
+ 'to',
1077
+ 'transitive',
1078
+ 'uses',
1079
+ 'vocabulary'
1080
+ ]);