@oml/language 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/oml/oml-candidates.d.ts +17 -7
- package/out/oml/oml-candidates.js +121 -19
- package/out/oml/oml-candidates.js.map +1 -1
- package/out/oml/oml-completion.js +2 -1
- package/out/oml/oml-completion.js.map +1 -1
- package/out/oml/oml-document.d.ts +4 -4
- package/out/oml/oml-document.js +42 -7
- package/out/oml/oml-document.js.map +1 -1
- package/out/oml/oml-edit.d.ts +12 -0
- package/out/oml/oml-edit.js +190 -40
- package/out/oml/oml-edit.js.map +1 -1
- package/out/oml/oml-index.d.ts +25 -6
- package/out/oml/oml-index.js +296 -43
- package/out/oml/oml-index.js.map +1 -1
- package/out/oml/oml-rename.js +19 -1
- package/out/oml/oml-rename.js.map +1 -1
- package/out/oml/oml-utils.js +1 -0
- package/out/oml/oml-utils.js.map +1 -1
- package/package.json +1 -1
- package/src/oml/oml-candidates.ts +146 -21
- package/src/oml/oml-completion.ts +2 -1
- package/src/oml/oml-document.ts +49 -9
- package/src/oml/oml-edit.ts +200 -39
- package/src/oml/oml-index.ts +320 -44
- package/src/oml/oml-rename.ts +21 -1
- package/src/oml/oml-utils.ts +1 -0
- package/out/oml/oml-index-manager.d.ts +0 -10
- package/out/oml/oml-index-manager.js +0 -48
- package/out/oml/oml-index-manager.js.map +0 -1
- package/src/oml/oml-index-manager.ts +0 -56
package/src/oml/oml-edit.ts
CHANGED
|
@@ -6,12 +6,15 @@ import {
|
|
|
6
6
|
isAnnotation,
|
|
7
7
|
isConceptInstance,
|
|
8
8
|
isDescription,
|
|
9
|
+
isDescriptionBox,
|
|
9
10
|
isImport,
|
|
10
11
|
isOntology,
|
|
11
12
|
isPropertyValueAssertion,
|
|
12
13
|
isRelationInstance,
|
|
13
14
|
isRule,
|
|
14
15
|
isTypeAssertion,
|
|
16
|
+
isVocabulary,
|
|
17
|
+
isVocabularyBundle,
|
|
15
18
|
} from './generated/ast.js';
|
|
16
19
|
import { getOntologyModelIndex } from './oml-index.js';
|
|
17
20
|
import { serializeOntology } from './oml-serializer.js';
|
|
@@ -40,8 +43,10 @@ type OmlEditOperation =
|
|
|
40
43
|
| { kind: 'createInstanceRef'; ontologyIri: string; instanceIri: string; typeIri?: string }
|
|
41
44
|
| { kind: 'createRelationInstanceRef'; ontologyIri: string; instanceIri: string; typeIri?: string }
|
|
42
45
|
| { kind: 'addAssertion'; ontologyIri: string; subjectIri: string; predicateIri: string; object: unknown }
|
|
46
|
+
| { kind: 'updateAssertion'; ontologyIri: string; subjectIri: string; predicateIri: string; object: unknown }
|
|
43
47
|
| { kind: 'removeAssertion'; ontologyIri: string; subjectIri: string; predicateIri: string; object?: unknown }
|
|
44
48
|
| { kind: 'addAnnotation'; ontologyIri: string; subjectIri: string; predicateIri: string; object: unknown }
|
|
49
|
+
| { kind: 'updateAnnotation'; ontologyIri: string; subjectIri: string; predicateIri: string; object: unknown }
|
|
45
50
|
| { kind: 'removeAnnotation'; ontologyIri: string; subjectIri: string; predicateIri: string; object?: unknown }
|
|
46
51
|
| { kind: 'deleteMemberCascade'; ontologyIri: string; memberIri: string }
|
|
47
52
|
| { kind: 'deleteMemberRef'; ontologyIri: string; memberIri: string; typeIri?: string };
|
|
@@ -149,8 +154,7 @@ async function executeOperation(
|
|
|
149
154
|
ownedPropertyValues: [],
|
|
150
155
|
ownedTypes: []
|
|
151
156
|
};
|
|
152
|
-
|
|
153
|
-
context.ontology.ownedStatements.push(statement);
|
|
157
|
+
pushAstArrayChild(context.ontology, 'ownedStatements', statement);
|
|
154
158
|
}
|
|
155
159
|
return new Set([context.ontologyIri]);
|
|
156
160
|
case 'createRelationInstance':
|
|
@@ -166,15 +170,14 @@ async function executeOperation(
|
|
|
166
170
|
sources: [],
|
|
167
171
|
targets: []
|
|
168
172
|
};
|
|
169
|
-
|
|
170
|
-
context.ontology.ownedStatements.push(statement);
|
|
173
|
+
pushAstArrayChild(context.ontology, 'ownedStatements', statement);
|
|
171
174
|
}
|
|
172
175
|
return new Set([context.ontologyIri]);
|
|
173
176
|
case 'createInstanceRef':
|
|
174
177
|
ensureDescriptionOntology(context.ontology, operation.kind);
|
|
175
|
-
ensureReferenceImport(context.ontology, operation.instanceIri);
|
|
178
|
+
await ensureReferenceImport(shared, context.ontology, operation.instanceIri);
|
|
176
179
|
if (operation.typeIri) {
|
|
177
|
-
ensureReferenceImport(context.ontology, operation.typeIri);
|
|
180
|
+
await ensureReferenceImport(shared, context.ontology, operation.typeIri);
|
|
178
181
|
}
|
|
179
182
|
{
|
|
180
183
|
const ownedTypes: any[] = [];
|
|
@@ -192,15 +195,17 @@ async function executeOperation(
|
|
|
192
195
|
ownedTypes
|
|
193
196
|
};
|
|
194
197
|
statement.__targetIri = normalizeIri(operation.instanceIri);
|
|
195
|
-
|
|
196
|
-
|
|
198
|
+
pushAstArrayChild(context.ontology, 'ownedStatements', statement);
|
|
199
|
+
for (const typeAssertion of ownedTypes) {
|
|
200
|
+
attachAstNode(typeAssertion, statement, 'ownedTypes');
|
|
201
|
+
}
|
|
197
202
|
}
|
|
198
203
|
return new Set([context.ontologyIri]);
|
|
199
204
|
case 'createRelationInstanceRef':
|
|
200
205
|
ensureDescriptionOntology(context.ontology, operation.kind);
|
|
201
|
-
ensureReferenceImport(context.ontology, operation.instanceIri);
|
|
206
|
+
await ensureReferenceImport(shared, context.ontology, operation.instanceIri);
|
|
202
207
|
if (operation.typeIri) {
|
|
203
|
-
ensureReferenceImport(context.ontology, operation.typeIri);
|
|
208
|
+
await ensureReferenceImport(shared, context.ontology, operation.typeIri);
|
|
204
209
|
}
|
|
205
210
|
{
|
|
206
211
|
const ownedTypes: any[] = [];
|
|
@@ -220,13 +225,20 @@ async function executeOperation(
|
|
|
220
225
|
targets: []
|
|
221
226
|
};
|
|
222
227
|
statement.__targetIri = normalizeIri(operation.instanceIri);
|
|
223
|
-
|
|
224
|
-
|
|
228
|
+
pushAstArrayChild(context.ontology, 'ownedStatements', statement);
|
|
229
|
+
for (const typeAssertion of ownedTypes) {
|
|
230
|
+
attachAstNode(typeAssertion, statement, 'ownedTypes');
|
|
231
|
+
}
|
|
225
232
|
}
|
|
226
233
|
return new Set([context.ontologyIri]);
|
|
227
234
|
case 'addAssertion':
|
|
228
235
|
ensureDescriptionOntology(context.ontology, operation.kind);
|
|
229
|
-
return addAssertion(context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
|
|
236
|
+
return await addAssertion(shared, context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
|
|
237
|
+
? new Set([context.ontologyIri])
|
|
238
|
+
: new Set();
|
|
239
|
+
case 'updateAssertion':
|
|
240
|
+
ensureDescriptionOntology(context.ontology, operation.kind);
|
|
241
|
+
return await updateAssertion(shared, context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
|
|
230
242
|
? new Set([context.ontologyIri])
|
|
231
243
|
: new Set();
|
|
232
244
|
case 'removeAssertion':
|
|
@@ -235,7 +247,11 @@ async function executeOperation(
|
|
|
235
247
|
? new Set([context.ontologyIri])
|
|
236
248
|
: new Set();
|
|
237
249
|
case 'addAnnotation':
|
|
238
|
-
return addAnnotation(context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
|
|
250
|
+
return await addAnnotation(shared, context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
|
|
251
|
+
? new Set([context.ontologyIri])
|
|
252
|
+
: new Set();
|
|
253
|
+
case 'updateAnnotation':
|
|
254
|
+
return await updateAnnotation(shared, context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
|
|
239
255
|
? new Set([context.ontologyIri])
|
|
240
256
|
: new Set();
|
|
241
257
|
case 'removeAnnotation':
|
|
@@ -297,7 +313,7 @@ function ensureUniqueLocalName(ontology: any, memberName: string): void {
|
|
|
297
313
|
}
|
|
298
314
|
}
|
|
299
315
|
|
|
300
|
-
function addAssertion(ontology: any, subjectIri: string, predicateIri: string, objectValue: unknown): boolean {
|
|
316
|
+
async function addAssertion(shared: any, ontology: any, subjectIri: string, predicateIri: string, objectValue: unknown): Promise<boolean> {
|
|
301
317
|
const normalizedPredicate = normalizeIri(predicateIri);
|
|
302
318
|
const subject = findNamedInstanceByIri(ontology, subjectIri);
|
|
303
319
|
if (!subject) {
|
|
@@ -309,9 +325,9 @@ function addAssertion(ontology: any, subjectIri: string, predicateIri: string, o
|
|
|
309
325
|
if ((subject.ownedTypes ?? []).some((entry: any) => matchesPredicateRef(ontology, entry?.type, normalizedTypeIri))) {
|
|
310
326
|
return false;
|
|
311
327
|
}
|
|
312
|
-
ensureReferenceImport(ontology, normalizedTypeIri);
|
|
328
|
+
await ensureReferenceImport(shared, ontology, normalizedTypeIri);
|
|
313
329
|
subject.ownedTypes ??= [];
|
|
314
|
-
subject
|
|
330
|
+
pushAstArrayChild(subject, 'ownedTypes', {
|
|
315
331
|
$type: 'TypeAssertion',
|
|
316
332
|
type: asRef(ontology, normalizedTypeIri)
|
|
317
333
|
});
|
|
@@ -323,7 +339,7 @@ function addAssertion(ontology: any, subjectIri: string, predicateIri: string, o
|
|
|
323
339
|
throw new Error(`Predicate '${predicateIri}' applies only to relation instances.`);
|
|
324
340
|
}
|
|
325
341
|
const sourceIri = normalizeIri(asRequiredIri(objectValue, 'source assertion object'));
|
|
326
|
-
ensureReferenceImport(ontology, sourceIri);
|
|
342
|
+
await ensureReferenceImport(shared, ontology, sourceIri);
|
|
327
343
|
subject.sources ??= [];
|
|
328
344
|
subject.sources.push(asRef(ontology, sourceIri));
|
|
329
345
|
return true;
|
|
@@ -334,7 +350,7 @@ function addAssertion(ontology: any, subjectIri: string, predicateIri: string, o
|
|
|
334
350
|
throw new Error(`Predicate '${predicateIri}' applies only to relation instances.`);
|
|
335
351
|
}
|
|
336
352
|
const targetIri = normalizeIri(asRequiredIri(objectValue, 'target assertion object'));
|
|
337
|
-
ensureReferenceImport(ontology, targetIri);
|
|
353
|
+
await ensureReferenceImport(shared, ontology, targetIri);
|
|
338
354
|
subject.targets ??= [];
|
|
339
355
|
subject.targets.push(asRef(ontology, targetIri));
|
|
340
356
|
return true;
|
|
@@ -343,6 +359,7 @@ function addAssertion(ontology: any, subjectIri: string, predicateIri: string, o
|
|
|
343
359
|
subject.ownedPropertyValues ??= [];
|
|
344
360
|
let propertyAssertion = subject.ownedPropertyValues.find((assertion: any) => matchesPredicateRef(ontology, assertion?.property, normalizedPredicate));
|
|
345
361
|
if (!propertyAssertion) {
|
|
362
|
+
await ensureReferenceImport(shared, ontology, normalizedPredicate);
|
|
346
363
|
propertyAssertion = {
|
|
347
364
|
$type: 'PropertyValueAssertion',
|
|
348
365
|
property: asRef(ontology, normalizedPredicate),
|
|
@@ -350,7 +367,12 @@ function addAssertion(ontology: any, subjectIri: string, predicateIri: string, o
|
|
|
350
367
|
referencedValues: [],
|
|
351
368
|
containedValues: []
|
|
352
369
|
};
|
|
353
|
-
subject
|
|
370
|
+
pushAstArrayChild(subject, 'ownedPropertyValues', propertyAssertion);
|
|
371
|
+
}
|
|
372
|
+
if (isIriLike(objectValue)) {
|
|
373
|
+
await ensureReferenceImport(shared, ontology, normalizeIri(asRequiredIri(objectValue, 'assertion object')));
|
|
374
|
+
} else {
|
|
375
|
+
await ensureTypedLiteralDatatypeImport(shared, ontology, objectValue);
|
|
354
376
|
}
|
|
355
377
|
appendAssertionValue(ontology, propertyAssertion, objectValue);
|
|
356
378
|
return true;
|
|
@@ -447,20 +469,57 @@ function removeAssertion(ontology: any, subjectIri: string, predicateIri: string
|
|
|
447
469
|
return changed;
|
|
448
470
|
}
|
|
449
471
|
|
|
450
|
-
function
|
|
472
|
+
async function updateAssertion(shared: any, ontology: any, subjectIri: string, predicateIri: string, objectValue: unknown): Promise<boolean> {
|
|
473
|
+
const normalizedPredicate = normalizeIri(predicateIri);
|
|
474
|
+
const subject = findNamedInstanceByIri(ontology, subjectIri);
|
|
475
|
+
if (!subject) {
|
|
476
|
+
throw new Error(`Subject '${subjectIri}' was not found in the ontology.`);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
if (normalizedPredicate === RDF_TYPE_IRI || isSourcePredicate(normalizedPredicate) || isTargetPredicate(normalizedPredicate)) {
|
|
480
|
+
const removed = removeAssertion(ontology, subjectIri, predicateIri, undefined);
|
|
481
|
+
const added = await addAssertion(shared, ontology, subjectIri, predicateIri, objectValue);
|
|
482
|
+
return removed || added;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
subject.ownedPropertyValues ??= [];
|
|
486
|
+
let propertyAssertion = subject.ownedPropertyValues.find((assertion: any) => matchesPredicateRef(ontology, assertion?.property, normalizedPredicate));
|
|
487
|
+
if (!propertyAssertion) {
|
|
488
|
+
return addAssertion(shared, ontology, subjectIri, predicateIri, objectValue);
|
|
489
|
+
}
|
|
490
|
+
if (isIriLike(objectValue)) {
|
|
491
|
+
await ensureReferenceImport(shared, ontology, normalizeIri(asRequiredIri(objectValue, 'assertion object')));
|
|
492
|
+
} else {
|
|
493
|
+
await ensureTypedLiteralDatatypeImport(shared, ontology, objectValue);
|
|
494
|
+
}
|
|
495
|
+
propertyAssertion.literalValues = [];
|
|
496
|
+
propertyAssertion.referencedValues = [];
|
|
497
|
+
propertyAssertion.containedValues = [];
|
|
498
|
+
appendAssertionValue(ontology, propertyAssertion, objectValue);
|
|
499
|
+
return true;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
async function addAnnotation(shared: any, ontology: any, subjectIri: string, predicateIri: string, objectValue: unknown): Promise<boolean> {
|
|
451
503
|
const subject = findAnnotationSubjectByIri(ontology, subjectIri);
|
|
452
504
|
if (!subject) {
|
|
453
505
|
throw new Error(`Annotation subject '${subjectIri}' was not found in the ontology.`);
|
|
454
506
|
}
|
|
507
|
+
const normalizedPredicate = normalizeIri(predicateIri);
|
|
508
|
+
await ensureReferenceImport(shared, ontology, normalizedPredicate);
|
|
455
509
|
subject.ownedAnnotations ??= [];
|
|
456
510
|
const annotation: any = {
|
|
457
511
|
$type: 'Annotation',
|
|
458
|
-
property: asRef(ontology,
|
|
512
|
+
property: asRef(ontology, normalizedPredicate),
|
|
459
513
|
literalValues: [],
|
|
460
514
|
referencedValues: []
|
|
461
515
|
};
|
|
516
|
+
if (isIriLike(objectValue)) {
|
|
517
|
+
await ensureReferenceImport(shared, ontology, normalizeIri(asRequiredIri(objectValue, 'annotation object')));
|
|
518
|
+
} else {
|
|
519
|
+
await ensureTypedLiteralDatatypeImport(shared, ontology, objectValue);
|
|
520
|
+
}
|
|
462
521
|
appendAnnotationValue(ontology, annotation, objectValue);
|
|
463
|
-
subject
|
|
522
|
+
pushAstArrayChild(subject, 'ownedAnnotations', annotation);
|
|
464
523
|
return true;
|
|
465
524
|
}
|
|
466
525
|
|
|
@@ -502,6 +561,28 @@ function removeAnnotation(ontology: any, subjectIri: string, predicateIri: strin
|
|
|
502
561
|
return changed;
|
|
503
562
|
}
|
|
504
563
|
|
|
564
|
+
async function updateAnnotation(shared: any, ontology: any, subjectIri: string, predicateIri: string, objectValue: unknown): Promise<boolean> {
|
|
565
|
+
const subject = findAnnotationSubjectByIri(ontology, subjectIri);
|
|
566
|
+
if (!subject) {
|
|
567
|
+
throw new Error(`Annotation subject '${subjectIri}' was not found in the ontology.`);
|
|
568
|
+
}
|
|
569
|
+
const normalizedPredicate = normalizeIri(predicateIri);
|
|
570
|
+
subject.ownedAnnotations ??= [];
|
|
571
|
+
const annotation = subject.ownedAnnotations.find((entry: any) => matchesPredicateRef(ontology, entry?.property, normalizedPredicate));
|
|
572
|
+
if (!annotation) {
|
|
573
|
+
return addAnnotation(shared, ontology, subjectIri, predicateIri, objectValue);
|
|
574
|
+
}
|
|
575
|
+
if (isIriLike(objectValue)) {
|
|
576
|
+
await ensureReferenceImport(shared, ontology, normalizeIri(asRequiredIri(objectValue, 'annotation object')));
|
|
577
|
+
} else {
|
|
578
|
+
await ensureTypedLiteralDatatypeImport(shared, ontology, objectValue);
|
|
579
|
+
}
|
|
580
|
+
annotation.literalValues = [];
|
|
581
|
+
annotation.referencedValues = [];
|
|
582
|
+
appendAnnotationValue(ontology, annotation, objectValue);
|
|
583
|
+
return true;
|
|
584
|
+
}
|
|
585
|
+
|
|
505
586
|
function deleteMemberRef(ontology: any, memberIri: string, typeIri: string | undefined): boolean {
|
|
506
587
|
if (!Array.isArray(ontology.ownedStatements)) {
|
|
507
588
|
return false;
|
|
@@ -818,9 +899,7 @@ function matchesPredicateRef(ontology: any, ref: any, iri: string): boolean {
|
|
|
818
899
|
return false;
|
|
819
900
|
}
|
|
820
901
|
const normalizedWanted = normalizeIri(iri);
|
|
821
|
-
const refText =
|
|
822
|
-
? ref
|
|
823
|
-
: (typeof ref.$refText === 'string' ? ref.$refText : undefined);
|
|
902
|
+
const refText = getRefText(ref);
|
|
824
903
|
if (refText) {
|
|
825
904
|
const normalizedRefText = normalizeIri(expandRefTextToIri(ontology, refText) ?? refText);
|
|
826
905
|
if (isSameIriTarget(normalizedRefText, normalizedWanted)) {
|
|
@@ -835,13 +914,12 @@ function matchesPredicateRef(ontology: any, ref: any, iri: string): boolean {
|
|
|
835
914
|
function appendAssertionValue(ontology: any, assertion: any, objectValue: unknown): void {
|
|
836
915
|
if (isIriLike(objectValue)) {
|
|
837
916
|
const normalizedObjectIri = normalizeIri(asRequiredIri(objectValue, 'assertion object'));
|
|
838
|
-
ensureReferenceImport(ontology, normalizedObjectIri);
|
|
839
917
|
assertion.referencedValues ??= [];
|
|
840
918
|
assertion.referencedValues.push(asRef(ontology, normalizedObjectIri));
|
|
841
919
|
return;
|
|
842
920
|
}
|
|
843
921
|
assertion.literalValues ??= [];
|
|
844
|
-
assertion
|
|
922
|
+
pushAstArrayChild(assertion, 'literalValues', asLiteral(ontology, objectValue));
|
|
845
923
|
}
|
|
846
924
|
|
|
847
925
|
function removeAssertionValue(ontology: any, assertion: any, objectValue: unknown): void {
|
|
@@ -850,20 +928,19 @@ function removeAssertionValue(ontology: any, assertion: any, objectValue: unknow
|
|
|
850
928
|
assertion.referencedValues = (assertion.referencedValues ?? []).filter((ref: any) => !matchesPredicateRef(ontology, ref, normalizedIri));
|
|
851
929
|
return;
|
|
852
930
|
}
|
|
853
|
-
const normalizedLiteral = normalizeLiteralValue(asLiteral(objectValue));
|
|
931
|
+
const normalizedLiteral = normalizeLiteralValue(asLiteral(ontology, objectValue));
|
|
854
932
|
assertion.literalValues = (assertion.literalValues ?? []).filter((literal: any) => normalizeLiteralValue(literal) !== normalizedLiteral);
|
|
855
933
|
}
|
|
856
934
|
|
|
857
935
|
function appendAnnotationValue(ontology: any, annotation: any, objectValue: unknown): void {
|
|
858
936
|
if (isIriLike(objectValue)) {
|
|
859
937
|
const normalizedObjectIri = normalizeIri(asRequiredIri(objectValue, 'annotation object'));
|
|
860
|
-
ensureReferenceImport(ontology, normalizedObjectIri);
|
|
861
938
|
annotation.referencedValues ??= [];
|
|
862
939
|
annotation.referencedValues.push(asRef(ontology, normalizedObjectIri));
|
|
863
940
|
return;
|
|
864
941
|
}
|
|
865
942
|
annotation.literalValues ??= [];
|
|
866
|
-
annotation
|
|
943
|
+
pushAstArrayChild(annotation, 'literalValues', asLiteral(ontology, objectValue));
|
|
867
944
|
}
|
|
868
945
|
|
|
869
946
|
function removeAnnotationValue(ontology: any, annotation: any, objectValue: unknown): void {
|
|
@@ -872,7 +949,7 @@ function removeAnnotationValue(ontology: any, annotation: any, objectValue: unkn
|
|
|
872
949
|
annotation.referencedValues = (annotation.referencedValues ?? []).filter((ref: any) => !matchesPredicateRef(ontology, ref, normalizedIri));
|
|
873
950
|
return;
|
|
874
951
|
}
|
|
875
|
-
const normalizedLiteral = normalizeLiteralValue(asLiteral(objectValue));
|
|
952
|
+
const normalizedLiteral = normalizeLiteralValue(asLiteral(ontology, objectValue));
|
|
876
953
|
annotation.literalValues = (annotation.literalValues ?? []).filter((literal: any) => normalizeLiteralValue(literal) !== normalizedLiteral);
|
|
877
954
|
}
|
|
878
955
|
|
|
@@ -1006,7 +1083,7 @@ function expandLocalRefText(rawNamespace: string | undefined, localName: string)
|
|
|
1006
1083
|
return `${namespace}#${local}`;
|
|
1007
1084
|
}
|
|
1008
1085
|
|
|
1009
|
-
function ensureReferenceImport(ontology: any, iri: string): void {
|
|
1086
|
+
async function ensureReferenceImport(shared: any, ontology: any, iri: string): Promise<void> {
|
|
1010
1087
|
const target = parseIriParts(iri);
|
|
1011
1088
|
if (!target) {
|
|
1012
1089
|
return;
|
|
@@ -1036,17 +1113,55 @@ function ensureReferenceImport(ontology: any, iri: string): void {
|
|
|
1036
1113
|
}
|
|
1037
1114
|
const prefix = pickImportPrefix(target.namespace, usedPrefixes);
|
|
1038
1115
|
const importedRef = `<${target.namespace}${target.separator}>`;
|
|
1116
|
+
const importKind = await resolveImportKind(shared, ontology, target.namespace);
|
|
1039
1117
|
const importStatement: any = {
|
|
1040
1118
|
$type: 'Import',
|
|
1041
|
-
kind:
|
|
1119
|
+
kind: importKind,
|
|
1042
1120
|
prefix,
|
|
1043
1121
|
imported: { $refText: importedRef }
|
|
1044
1122
|
};
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1123
|
+
pushAstArrayChild(ontology, 'ownedImports', importStatement);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
async function resolveImportKind(shared: any, importing: any, importedNamespace: string): Promise<'extends' | 'includes' | 'uses'> {
|
|
1127
|
+
const imported = await findOntologyByNamespace(shared, importedNamespace);
|
|
1128
|
+
if (imported) {
|
|
1129
|
+
if (importing.$type === imported.$type) {
|
|
1130
|
+
return 'extends';
|
|
1131
|
+
}
|
|
1132
|
+
if (isVocabulary(importing) && isDescription(imported)) {
|
|
1133
|
+
return 'uses';
|
|
1134
|
+
}
|
|
1135
|
+
if (isDescriptionBox(importing) && isVocabulary(imported)) {
|
|
1136
|
+
return 'uses';
|
|
1137
|
+
}
|
|
1138
|
+
if (isVocabularyBundle(importing) && isVocabulary(imported)) {
|
|
1139
|
+
return 'includes';
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
if (isVocabularyBundle(importing)) {
|
|
1143
|
+
return 'includes';
|
|
1144
|
+
}
|
|
1145
|
+
if (isDescriptionBox(importing)) {
|
|
1146
|
+
return 'uses';
|
|
1048
1147
|
}
|
|
1049
|
-
|
|
1148
|
+
return 'extends';
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
async function findOntologyByNamespace(shared: any, namespace: string): Promise<any | undefined> {
|
|
1152
|
+
const index = getOntologyModelIndex(shared);
|
|
1153
|
+
const modelUri = index.resolveModelUri(normalizeNamespace(namespace));
|
|
1154
|
+
if (!modelUri) {
|
|
1155
|
+
return undefined;
|
|
1156
|
+
}
|
|
1157
|
+
const uri = URI.parse(modelUri);
|
|
1158
|
+
const langiumDocuments: any = shared.workspace.LangiumDocuments;
|
|
1159
|
+
const builder: any = shared.workspace.DocumentBuilder;
|
|
1160
|
+
const document = langiumDocuments.getDocument(uri)
|
|
1161
|
+
?? await langiumDocuments.getOrCreateDocument(uri);
|
|
1162
|
+
await builder.build([document], { validation: false });
|
|
1163
|
+
const ontology = document?.parseResult?.value;
|
|
1164
|
+
return ontology && isOntology(ontology) ? ontology : undefined;
|
|
1050
1165
|
}
|
|
1051
1166
|
|
|
1052
1167
|
function parseIriParts(iri: string): { namespace: string; fragment: string; separator: '#' | '/' } | undefined {
|
|
@@ -1198,7 +1313,17 @@ function pickImportPrefix(namespace: string, usedPrefixes: ReadonlySet<string>):
|
|
|
1198
1313
|
return `${candidateBase}${suffix}`;
|
|
1199
1314
|
}
|
|
1200
1315
|
|
|
1201
|
-
function asLiteral(value: unknown): any {
|
|
1316
|
+
function asLiteral(ontology: any, value: unknown): any {
|
|
1317
|
+
if (isTypedQuotedLiteralTransport(value)) {
|
|
1318
|
+
const literalValue = String(value.value ?? '');
|
|
1319
|
+
const datatypeIri = typeof value.datatypeIri === 'string' ? value.datatypeIri.trim() : '';
|
|
1320
|
+
const datatypeRefText = typeof value.datatypeRefText === 'string' ? value.datatypeRefText.trim() : '';
|
|
1321
|
+
return datatypeIri
|
|
1322
|
+
? { $type: 'QuotedLiteral', value: literalValue, type: { $refText: toRefText(ontology, normalizeIri(datatypeIri)) } }
|
|
1323
|
+
: datatypeRefText
|
|
1324
|
+
? { $type: 'QuotedLiteral', value: literalValue, type: { $refText: datatypeRefText } }
|
|
1325
|
+
: { $type: 'QuotedLiteral', value: literalValue };
|
|
1326
|
+
}
|
|
1202
1327
|
if (typeof value === 'boolean') {
|
|
1203
1328
|
return { $type: 'BooleanLiteral', value };
|
|
1204
1329
|
}
|
|
@@ -1211,6 +1336,42 @@ function asLiteral(value: unknown): any {
|
|
|
1211
1336
|
return { $type: 'QuotedLiteral', value: String(value ?? '') };
|
|
1212
1337
|
}
|
|
1213
1338
|
|
|
1339
|
+
async function ensureTypedLiteralDatatypeImport(shared: any, ontology: any, value: unknown): Promise<void> {
|
|
1340
|
+
if (!isTypedQuotedLiteralTransport(value)) {
|
|
1341
|
+
return;
|
|
1342
|
+
}
|
|
1343
|
+
const datatypeIri = typeof value.datatypeIri === 'string' ? normalizeIri(value.datatypeIri) : '';
|
|
1344
|
+
if (!datatypeIri) {
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1347
|
+
await ensureReferenceImport(shared, ontology, datatypeIri);
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
function isTypedQuotedLiteralTransport(value: unknown): value is { $type?: unknown; value?: unknown; datatypeIri?: unknown; datatypeRefText?: unknown } {
|
|
1351
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
1352
|
+
return false;
|
|
1353
|
+
}
|
|
1354
|
+
const record = value as Record<string, unknown>;
|
|
1355
|
+
if (record.$type === 'QuotedLiteral') {
|
|
1356
|
+
return true;
|
|
1357
|
+
}
|
|
1358
|
+
return (typeof record.datatypeIri === 'string' || typeof record.datatypeRefText === 'string') && 'value' in record;
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
function attachAstNode<T extends Record<string, any>>(node: T, parent: any, containerProperty: string): T {
|
|
1362
|
+
(node as any).$container = parent;
|
|
1363
|
+
(node as any).$containerProperty = containerProperty;
|
|
1364
|
+
return node;
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
function pushAstArrayChild(parent: any, property: string, node: any): void {
|
|
1368
|
+
if (!Array.isArray(parent[property])) {
|
|
1369
|
+
parent[property] = [];
|
|
1370
|
+
}
|
|
1371
|
+
attachAstNode(node, parent, property);
|
|
1372
|
+
parent[property].push(node);
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1214
1375
|
function asRequiredIri(value: unknown, context: string): string {
|
|
1215
1376
|
if (!isIriLike(value)) {
|
|
1216
1377
|
throw new Error(`Expected IRI for ${context}.`);
|