@oml/language 0.9.0 → 0.11.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 +119 -21
- 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 +201 -43
- package/out/oml/oml-edit.js.map +1 -1
- package/out/oml/oml-index.d.ts +26 -6
- package/out/oml/oml-index.js +305 -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 +144 -23
- package/src/oml/oml-completion.ts +2 -1
- package/src/oml/oml-document.ts +49 -9
- package/src/oml/oml-edit.ts +211 -42
- package/src/oml/oml-index.ts +330 -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/out/oml/oml-edit.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright (c) 2026 Modelware. All rights reserved.
|
|
2
|
-
import { URI } from 'langium';
|
|
2
|
+
import { DocumentState, URI } from 'langium';
|
|
3
3
|
import { RequestType } from 'vscode-languageserver-protocol';
|
|
4
|
-
import { isAnnotation, isConceptInstance, isDescription, isImport, isOntology, isPropertyValueAssertion, isRelationInstance, isRule, isTypeAssertion, } from './generated/ast.js';
|
|
4
|
+
import { isAnnotation, isConceptInstance, isDescription, isDescriptionBox, isImport, isOntology, isPropertyValueAssertion, isRelationInstance, isRule, isTypeAssertion, isVocabulary, isVocabularyBundle, } from './generated/ast.js';
|
|
5
5
|
import { getOntologyModelIndex } from './oml-index.js';
|
|
6
6
|
import { serializeOntology } from './oml-serializer.js';
|
|
7
7
|
import { collectOntologyMembers, findOntologyMemberByName, getIriForNode, normalizeNamespace, } from './oml-utils.js';
|
|
@@ -58,7 +58,12 @@ async function resolveOntologyContext(shared, ontologyIri, cache) {
|
|
|
58
58
|
const builder = shared.workspace.DocumentBuilder;
|
|
59
59
|
const document = langiumDocuments.getDocument(uri)
|
|
60
60
|
?? await langiumDocuments.getOrCreateDocument(uri);
|
|
61
|
-
|
|
61
|
+
// Only build if not yet Linked. Forcing validation:true when the workspace
|
|
62
|
+
// is already Validated causes a document-state conflict in Langium on Windows.
|
|
63
|
+
const docState = document?.state;
|
|
64
|
+
if (docState === undefined || docState < DocumentState.Linked) {
|
|
65
|
+
await builder.build([document], { validation: false });
|
|
66
|
+
}
|
|
62
67
|
const ontology = document?.parseResult?.value;
|
|
63
68
|
if (!ontology || !isOntology(ontology)) {
|
|
64
69
|
throw new Error(`Resolved document '${modelUri}' is not an ontology.`);
|
|
@@ -85,8 +90,7 @@ async function executeOperation(shared, context, operation, contexts) {
|
|
|
85
90
|
ownedPropertyValues: [],
|
|
86
91
|
ownedTypes: []
|
|
87
92
|
};
|
|
88
|
-
|
|
89
|
-
context.ontology.ownedStatements.push(statement);
|
|
93
|
+
pushAstArrayChild(context.ontology, 'ownedStatements', statement);
|
|
90
94
|
}
|
|
91
95
|
return new Set([context.ontologyIri]);
|
|
92
96
|
case 'createRelationInstance':
|
|
@@ -102,15 +106,14 @@ async function executeOperation(shared, context, operation, contexts) {
|
|
|
102
106
|
sources: [],
|
|
103
107
|
targets: []
|
|
104
108
|
};
|
|
105
|
-
|
|
106
|
-
context.ontology.ownedStatements.push(statement);
|
|
109
|
+
pushAstArrayChild(context.ontology, 'ownedStatements', statement);
|
|
107
110
|
}
|
|
108
111
|
return new Set([context.ontologyIri]);
|
|
109
112
|
case 'createInstanceRef':
|
|
110
113
|
ensureDescriptionOntology(context.ontology, operation.kind);
|
|
111
|
-
ensureReferenceImport(context.ontology, operation.instanceIri);
|
|
114
|
+
await ensureReferenceImport(shared, context.ontology, operation.instanceIri);
|
|
112
115
|
if (operation.typeIri) {
|
|
113
|
-
ensureReferenceImport(context.ontology, operation.typeIri);
|
|
116
|
+
await ensureReferenceImport(shared, context.ontology, operation.typeIri);
|
|
114
117
|
}
|
|
115
118
|
{
|
|
116
119
|
const ownedTypes = [];
|
|
@@ -128,15 +131,17 @@ async function executeOperation(shared, context, operation, contexts) {
|
|
|
128
131
|
ownedTypes
|
|
129
132
|
};
|
|
130
133
|
statement.__targetIri = normalizeIri(operation.instanceIri);
|
|
131
|
-
|
|
132
|
-
|
|
134
|
+
pushAstArrayChild(context.ontology, 'ownedStatements', statement);
|
|
135
|
+
for (const typeAssertion of ownedTypes) {
|
|
136
|
+
attachAstNode(typeAssertion, statement, 'ownedTypes');
|
|
137
|
+
}
|
|
133
138
|
}
|
|
134
139
|
return new Set([context.ontologyIri]);
|
|
135
140
|
case 'createRelationInstanceRef':
|
|
136
141
|
ensureDescriptionOntology(context.ontology, operation.kind);
|
|
137
|
-
ensureReferenceImport(context.ontology, operation.instanceIri);
|
|
142
|
+
await ensureReferenceImport(shared, context.ontology, operation.instanceIri);
|
|
138
143
|
if (operation.typeIri) {
|
|
139
|
-
ensureReferenceImport(context.ontology, operation.typeIri);
|
|
144
|
+
await ensureReferenceImport(shared, context.ontology, operation.typeIri);
|
|
140
145
|
}
|
|
141
146
|
{
|
|
142
147
|
const ownedTypes = [];
|
|
@@ -156,13 +161,20 @@ async function executeOperation(shared, context, operation, contexts) {
|
|
|
156
161
|
targets: []
|
|
157
162
|
};
|
|
158
163
|
statement.__targetIri = normalizeIri(operation.instanceIri);
|
|
159
|
-
|
|
160
|
-
|
|
164
|
+
pushAstArrayChild(context.ontology, 'ownedStatements', statement);
|
|
165
|
+
for (const typeAssertion of ownedTypes) {
|
|
166
|
+
attachAstNode(typeAssertion, statement, 'ownedTypes');
|
|
167
|
+
}
|
|
161
168
|
}
|
|
162
169
|
return new Set([context.ontologyIri]);
|
|
163
170
|
case 'addAssertion':
|
|
164
171
|
ensureDescriptionOntology(context.ontology, operation.kind);
|
|
165
|
-
return addAssertion(context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
|
|
172
|
+
return await addAssertion(shared, context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
|
|
173
|
+
? new Set([context.ontologyIri])
|
|
174
|
+
: new Set();
|
|
175
|
+
case 'updateAssertion':
|
|
176
|
+
ensureDescriptionOntology(context.ontology, operation.kind);
|
|
177
|
+
return await updateAssertion(shared, context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
|
|
166
178
|
? new Set([context.ontologyIri])
|
|
167
179
|
: new Set();
|
|
168
180
|
case 'removeAssertion':
|
|
@@ -171,7 +183,11 @@ async function executeOperation(shared, context, operation, contexts) {
|
|
|
171
183
|
? new Set([context.ontologyIri])
|
|
172
184
|
: new Set();
|
|
173
185
|
case 'addAnnotation':
|
|
174
|
-
return addAnnotation(context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
|
|
186
|
+
return await addAnnotation(shared, context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
|
|
187
|
+
? new Set([context.ontologyIri])
|
|
188
|
+
: new Set();
|
|
189
|
+
case 'updateAnnotation':
|
|
190
|
+
return await updateAnnotation(shared, context.ontology, operation.subjectIri, operation.predicateIri, operation.object)
|
|
175
191
|
? new Set([context.ontologyIri])
|
|
176
192
|
: new Set();
|
|
177
193
|
case 'removeAnnotation':
|
|
@@ -200,7 +216,10 @@ async function resolveOntologyContextByModelUri(shared, modelUri, cache) {
|
|
|
200
216
|
const builder = shared.workspace.DocumentBuilder;
|
|
201
217
|
const document = langiumDocuments.getDocument(uri)
|
|
202
218
|
?? await langiumDocuments.getOrCreateDocument(uri);
|
|
203
|
-
|
|
219
|
+
const docState2 = document?.state;
|
|
220
|
+
if (docState2 === undefined || docState2 < DocumentState.Linked) {
|
|
221
|
+
await builder.build([document], { validation: false });
|
|
222
|
+
}
|
|
204
223
|
const ontology = document?.parseResult?.value;
|
|
205
224
|
if (!ontology || !isOntology(ontology)) {
|
|
206
225
|
throw new Error(`Resolved document '${modelUri}' is not an ontology.`);
|
|
@@ -225,7 +244,7 @@ function ensureUniqueLocalName(ontology, memberName) {
|
|
|
225
244
|
throw new Error(`A member named '${memberName}' already exists in the ontology.`);
|
|
226
245
|
}
|
|
227
246
|
}
|
|
228
|
-
function addAssertion(ontology, subjectIri, predicateIri, objectValue) {
|
|
247
|
+
async function addAssertion(shared, ontology, subjectIri, predicateIri, objectValue) {
|
|
229
248
|
const normalizedPredicate = normalizeIri(predicateIri);
|
|
230
249
|
const subject = findNamedInstanceByIri(ontology, subjectIri);
|
|
231
250
|
if (!subject) {
|
|
@@ -236,9 +255,9 @@ function addAssertion(ontology, subjectIri, predicateIri, objectValue) {
|
|
|
236
255
|
if ((subject.ownedTypes ?? []).some((entry) => matchesPredicateRef(ontology, entry?.type, normalizedTypeIri))) {
|
|
237
256
|
return false;
|
|
238
257
|
}
|
|
239
|
-
ensureReferenceImport(ontology, normalizedTypeIri);
|
|
258
|
+
await ensureReferenceImport(shared, ontology, normalizedTypeIri);
|
|
240
259
|
subject.ownedTypes ?? (subject.ownedTypes = []);
|
|
241
|
-
subject
|
|
260
|
+
pushAstArrayChild(subject, 'ownedTypes', {
|
|
242
261
|
$type: 'TypeAssertion',
|
|
243
262
|
type: asRef(ontology, normalizedTypeIri)
|
|
244
263
|
});
|
|
@@ -249,7 +268,7 @@ function addAssertion(ontology, subjectIri, predicateIri, objectValue) {
|
|
|
249
268
|
throw new Error(`Predicate '${predicateIri}' applies only to relation instances.`);
|
|
250
269
|
}
|
|
251
270
|
const sourceIri = normalizeIri(asRequiredIri(objectValue, 'source assertion object'));
|
|
252
|
-
ensureReferenceImport(ontology, sourceIri);
|
|
271
|
+
await ensureReferenceImport(shared, ontology, sourceIri);
|
|
253
272
|
subject.sources ?? (subject.sources = []);
|
|
254
273
|
subject.sources.push(asRef(ontology, sourceIri));
|
|
255
274
|
return true;
|
|
@@ -259,7 +278,7 @@ function addAssertion(ontology, subjectIri, predicateIri, objectValue) {
|
|
|
259
278
|
throw new Error(`Predicate '${predicateIri}' applies only to relation instances.`);
|
|
260
279
|
}
|
|
261
280
|
const targetIri = normalizeIri(asRequiredIri(objectValue, 'target assertion object'));
|
|
262
|
-
ensureReferenceImport(ontology, targetIri);
|
|
281
|
+
await ensureReferenceImport(shared, ontology, targetIri);
|
|
263
282
|
subject.targets ?? (subject.targets = []);
|
|
264
283
|
subject.targets.push(asRef(ontology, targetIri));
|
|
265
284
|
return true;
|
|
@@ -267,6 +286,7 @@ function addAssertion(ontology, subjectIri, predicateIri, objectValue) {
|
|
|
267
286
|
subject.ownedPropertyValues ?? (subject.ownedPropertyValues = []);
|
|
268
287
|
let propertyAssertion = subject.ownedPropertyValues.find((assertion) => matchesPredicateRef(ontology, assertion?.property, normalizedPredicate));
|
|
269
288
|
if (!propertyAssertion) {
|
|
289
|
+
await ensureReferenceImport(shared, ontology, normalizedPredicate);
|
|
270
290
|
propertyAssertion = {
|
|
271
291
|
$type: 'PropertyValueAssertion',
|
|
272
292
|
property: asRef(ontology, normalizedPredicate),
|
|
@@ -274,7 +294,13 @@ function addAssertion(ontology, subjectIri, predicateIri, objectValue) {
|
|
|
274
294
|
referencedValues: [],
|
|
275
295
|
containedValues: []
|
|
276
296
|
};
|
|
277
|
-
subject
|
|
297
|
+
pushAstArrayChild(subject, 'ownedPropertyValues', propertyAssertion);
|
|
298
|
+
}
|
|
299
|
+
if (isIriLike(objectValue)) {
|
|
300
|
+
await ensureReferenceImport(shared, ontology, normalizeIri(asRequiredIri(objectValue, 'assertion object')));
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
await ensureTypedLiteralDatatypeImport(shared, ontology, objectValue);
|
|
278
304
|
}
|
|
279
305
|
appendAssertionValue(ontology, propertyAssertion, objectValue);
|
|
280
306
|
return true;
|
|
@@ -367,20 +393,56 @@ function removeAssertion(ontology, subjectIri, predicateIri, objectValue) {
|
|
|
367
393
|
subject.ownedPropertyValues = remaining;
|
|
368
394
|
return changed;
|
|
369
395
|
}
|
|
370
|
-
function
|
|
396
|
+
async function updateAssertion(shared, ontology, subjectIri, predicateIri, objectValue) {
|
|
397
|
+
const normalizedPredicate = normalizeIri(predicateIri);
|
|
398
|
+
const subject = findNamedInstanceByIri(ontology, subjectIri);
|
|
399
|
+
if (!subject) {
|
|
400
|
+
throw new Error(`Subject '${subjectIri}' was not found in the ontology.`);
|
|
401
|
+
}
|
|
402
|
+
if (normalizedPredicate === RDF_TYPE_IRI || isSourcePredicate(normalizedPredicate) || isTargetPredicate(normalizedPredicate)) {
|
|
403
|
+
const removed = removeAssertion(ontology, subjectIri, predicateIri, undefined);
|
|
404
|
+
const added = await addAssertion(shared, ontology, subjectIri, predicateIri, objectValue);
|
|
405
|
+
return removed || added;
|
|
406
|
+
}
|
|
407
|
+
subject.ownedPropertyValues ?? (subject.ownedPropertyValues = []);
|
|
408
|
+
let propertyAssertion = subject.ownedPropertyValues.find((assertion) => matchesPredicateRef(ontology, assertion?.property, normalizedPredicate));
|
|
409
|
+
if (!propertyAssertion) {
|
|
410
|
+
return addAssertion(shared, ontology, subjectIri, predicateIri, objectValue);
|
|
411
|
+
}
|
|
412
|
+
if (isIriLike(objectValue)) {
|
|
413
|
+
await ensureReferenceImport(shared, ontology, normalizeIri(asRequiredIri(objectValue, 'assertion object')));
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
await ensureTypedLiteralDatatypeImport(shared, ontology, objectValue);
|
|
417
|
+
}
|
|
418
|
+
propertyAssertion.literalValues = [];
|
|
419
|
+
propertyAssertion.referencedValues = [];
|
|
420
|
+
propertyAssertion.containedValues = [];
|
|
421
|
+
appendAssertionValue(ontology, propertyAssertion, objectValue);
|
|
422
|
+
return true;
|
|
423
|
+
}
|
|
424
|
+
async function addAnnotation(shared, ontology, subjectIri, predicateIri, objectValue) {
|
|
371
425
|
const subject = findAnnotationSubjectByIri(ontology, subjectIri);
|
|
372
426
|
if (!subject) {
|
|
373
427
|
throw new Error(`Annotation subject '${subjectIri}' was not found in the ontology.`);
|
|
374
428
|
}
|
|
429
|
+
const normalizedPredicate = normalizeIri(predicateIri);
|
|
430
|
+
await ensureReferenceImport(shared, ontology, normalizedPredicate);
|
|
375
431
|
subject.ownedAnnotations ?? (subject.ownedAnnotations = []);
|
|
376
432
|
const annotation = {
|
|
377
433
|
$type: 'Annotation',
|
|
378
|
-
property: asRef(ontology,
|
|
434
|
+
property: asRef(ontology, normalizedPredicate),
|
|
379
435
|
literalValues: [],
|
|
380
436
|
referencedValues: []
|
|
381
437
|
};
|
|
438
|
+
if (isIriLike(objectValue)) {
|
|
439
|
+
await ensureReferenceImport(shared, ontology, normalizeIri(asRequiredIri(objectValue, 'annotation object')));
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
await ensureTypedLiteralDatatypeImport(shared, ontology, objectValue);
|
|
443
|
+
}
|
|
382
444
|
appendAnnotationValue(ontology, annotation, objectValue);
|
|
383
|
-
subject
|
|
445
|
+
pushAstArrayChild(subject, 'ownedAnnotations', annotation);
|
|
384
446
|
return true;
|
|
385
447
|
}
|
|
386
448
|
function removeAnnotation(ontology, subjectIri, predicateIri, objectValue) {
|
|
@@ -420,6 +482,28 @@ function removeAnnotation(ontology, subjectIri, predicateIri, objectValue) {
|
|
|
420
482
|
subject.ownedAnnotations = kept;
|
|
421
483
|
return changed;
|
|
422
484
|
}
|
|
485
|
+
async function updateAnnotation(shared, ontology, subjectIri, predicateIri, objectValue) {
|
|
486
|
+
const subject = findAnnotationSubjectByIri(ontology, subjectIri);
|
|
487
|
+
if (!subject) {
|
|
488
|
+
throw new Error(`Annotation subject '${subjectIri}' was not found in the ontology.`);
|
|
489
|
+
}
|
|
490
|
+
const normalizedPredicate = normalizeIri(predicateIri);
|
|
491
|
+
subject.ownedAnnotations ?? (subject.ownedAnnotations = []);
|
|
492
|
+
const annotation = subject.ownedAnnotations.find((entry) => matchesPredicateRef(ontology, entry?.property, normalizedPredicate));
|
|
493
|
+
if (!annotation) {
|
|
494
|
+
return addAnnotation(shared, ontology, subjectIri, predicateIri, objectValue);
|
|
495
|
+
}
|
|
496
|
+
if (isIriLike(objectValue)) {
|
|
497
|
+
await ensureReferenceImport(shared, ontology, normalizeIri(asRequiredIri(objectValue, 'annotation object')));
|
|
498
|
+
}
|
|
499
|
+
else {
|
|
500
|
+
await ensureTypedLiteralDatatypeImport(shared, ontology, objectValue);
|
|
501
|
+
}
|
|
502
|
+
annotation.literalValues = [];
|
|
503
|
+
annotation.referencedValues = [];
|
|
504
|
+
appendAnnotationValue(ontology, annotation, objectValue);
|
|
505
|
+
return true;
|
|
506
|
+
}
|
|
423
507
|
function deleteMemberRef(ontology, memberIri, typeIri) {
|
|
424
508
|
if (!Array.isArray(ontology.ownedStatements)) {
|
|
425
509
|
return false;
|
|
@@ -718,9 +802,7 @@ function matchesPredicateRef(ontology, ref, iri) {
|
|
|
718
802
|
return false;
|
|
719
803
|
}
|
|
720
804
|
const normalizedWanted = normalizeIri(iri);
|
|
721
|
-
const refText =
|
|
722
|
-
? ref
|
|
723
|
-
: (typeof ref.$refText === 'string' ? ref.$refText : undefined);
|
|
805
|
+
const refText = getRefText(ref);
|
|
724
806
|
if (refText) {
|
|
725
807
|
const normalizedRefText = normalizeIri(expandRefTextToIri(ontology, refText) ?? refText);
|
|
726
808
|
if (isSameIriTarget(normalizedRefText, normalizedWanted)) {
|
|
@@ -734,13 +816,12 @@ function matchesPredicateRef(ontology, ref, iri) {
|
|
|
734
816
|
function appendAssertionValue(ontology, assertion, objectValue) {
|
|
735
817
|
if (isIriLike(objectValue)) {
|
|
736
818
|
const normalizedObjectIri = normalizeIri(asRequiredIri(objectValue, 'assertion object'));
|
|
737
|
-
ensureReferenceImport(ontology, normalizedObjectIri);
|
|
738
819
|
assertion.referencedValues ?? (assertion.referencedValues = []);
|
|
739
820
|
assertion.referencedValues.push(asRef(ontology, normalizedObjectIri));
|
|
740
821
|
return;
|
|
741
822
|
}
|
|
742
823
|
assertion.literalValues ?? (assertion.literalValues = []);
|
|
743
|
-
assertion
|
|
824
|
+
pushAstArrayChild(assertion, 'literalValues', asLiteral(ontology, objectValue));
|
|
744
825
|
}
|
|
745
826
|
function removeAssertionValue(ontology, assertion, objectValue) {
|
|
746
827
|
if (isIriLike(objectValue)) {
|
|
@@ -748,19 +829,18 @@ function removeAssertionValue(ontology, assertion, objectValue) {
|
|
|
748
829
|
assertion.referencedValues = (assertion.referencedValues ?? []).filter((ref) => !matchesPredicateRef(ontology, ref, normalizedIri));
|
|
749
830
|
return;
|
|
750
831
|
}
|
|
751
|
-
const normalizedLiteral = normalizeLiteralValue(asLiteral(objectValue));
|
|
832
|
+
const normalizedLiteral = normalizeLiteralValue(asLiteral(ontology, objectValue));
|
|
752
833
|
assertion.literalValues = (assertion.literalValues ?? []).filter((literal) => normalizeLiteralValue(literal) !== normalizedLiteral);
|
|
753
834
|
}
|
|
754
835
|
function appendAnnotationValue(ontology, annotation, objectValue) {
|
|
755
836
|
if (isIriLike(objectValue)) {
|
|
756
837
|
const normalizedObjectIri = normalizeIri(asRequiredIri(objectValue, 'annotation object'));
|
|
757
|
-
ensureReferenceImport(ontology, normalizedObjectIri);
|
|
758
838
|
annotation.referencedValues ?? (annotation.referencedValues = []);
|
|
759
839
|
annotation.referencedValues.push(asRef(ontology, normalizedObjectIri));
|
|
760
840
|
return;
|
|
761
841
|
}
|
|
762
842
|
annotation.literalValues ?? (annotation.literalValues = []);
|
|
763
|
-
annotation
|
|
843
|
+
pushAstArrayChild(annotation, 'literalValues', asLiteral(ontology, objectValue));
|
|
764
844
|
}
|
|
765
845
|
function removeAnnotationValue(ontology, annotation, objectValue) {
|
|
766
846
|
if (isIriLike(objectValue)) {
|
|
@@ -768,7 +848,7 @@ function removeAnnotationValue(ontology, annotation, objectValue) {
|
|
|
768
848
|
annotation.referencedValues = (annotation.referencedValues ?? []).filter((ref) => !matchesPredicateRef(ontology, ref, normalizedIri));
|
|
769
849
|
return;
|
|
770
850
|
}
|
|
771
|
-
const normalizedLiteral = normalizeLiteralValue(asLiteral(objectValue));
|
|
851
|
+
const normalizedLiteral = normalizeLiteralValue(asLiteral(ontology, objectValue));
|
|
772
852
|
annotation.literalValues = (annotation.literalValues ?? []).filter((literal) => normalizeLiteralValue(literal) !== normalizedLiteral);
|
|
773
853
|
}
|
|
774
854
|
function normalizeLiteralValue(literal) {
|
|
@@ -893,7 +973,7 @@ function expandLocalRefText(rawNamespace, localName) {
|
|
|
893
973
|
}
|
|
894
974
|
return `${namespace}#${local}`;
|
|
895
975
|
}
|
|
896
|
-
function ensureReferenceImport(ontology, iri) {
|
|
976
|
+
async function ensureReferenceImport(shared, ontology, iri) {
|
|
897
977
|
const target = parseIriParts(iri);
|
|
898
978
|
if (!target) {
|
|
899
979
|
return;
|
|
@@ -923,17 +1003,53 @@ function ensureReferenceImport(ontology, iri) {
|
|
|
923
1003
|
}
|
|
924
1004
|
const prefix = pickImportPrefix(target.namespace, usedPrefixes);
|
|
925
1005
|
const importedRef = `<${target.namespace}${target.separator}>`;
|
|
1006
|
+
const importKind = await resolveImportKind(shared, ontology, target.namespace);
|
|
926
1007
|
const importStatement = {
|
|
927
1008
|
$type: 'Import',
|
|
928
|
-
kind:
|
|
1009
|
+
kind: importKind,
|
|
929
1010
|
prefix,
|
|
930
1011
|
imported: { $refText: importedRef }
|
|
931
1012
|
};
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
1013
|
+
pushAstArrayChild(ontology, 'ownedImports', importStatement);
|
|
1014
|
+
}
|
|
1015
|
+
async function resolveImportKind(shared, importing, importedNamespace) {
|
|
1016
|
+
const imported = await findOntologyByNamespace(shared, importedNamespace);
|
|
1017
|
+
if (imported) {
|
|
1018
|
+
if (importing.$type === imported.$type) {
|
|
1019
|
+
return 'extends';
|
|
1020
|
+
}
|
|
1021
|
+
if (isVocabulary(importing) && isDescription(imported)) {
|
|
1022
|
+
return 'uses';
|
|
1023
|
+
}
|
|
1024
|
+
if (isDescriptionBox(importing) && isVocabulary(imported)) {
|
|
1025
|
+
return 'uses';
|
|
1026
|
+
}
|
|
1027
|
+
if (isVocabularyBundle(importing) && isVocabulary(imported)) {
|
|
1028
|
+
return 'includes';
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
if (isVocabularyBundle(importing)) {
|
|
1032
|
+
return 'includes';
|
|
1033
|
+
}
|
|
1034
|
+
if (isDescriptionBox(importing)) {
|
|
1035
|
+
return 'uses';
|
|
935
1036
|
}
|
|
936
|
-
|
|
1037
|
+
return 'extends';
|
|
1038
|
+
}
|
|
1039
|
+
async function findOntologyByNamespace(shared, namespace) {
|
|
1040
|
+
const index = getOntologyModelIndex(shared);
|
|
1041
|
+
const modelUri = index.resolveModelUri(normalizeNamespace(namespace));
|
|
1042
|
+
if (!modelUri) {
|
|
1043
|
+
return undefined;
|
|
1044
|
+
}
|
|
1045
|
+
const uri = URI.parse(modelUri);
|
|
1046
|
+
const langiumDocuments = shared.workspace.LangiumDocuments;
|
|
1047
|
+
const builder = shared.workspace.DocumentBuilder;
|
|
1048
|
+
const document = langiumDocuments.getDocument(uri)
|
|
1049
|
+
?? await langiumDocuments.getOrCreateDocument(uri);
|
|
1050
|
+
await builder.build([document], { validation: false });
|
|
1051
|
+
const ontology = document?.parseResult?.value;
|
|
1052
|
+
return ontology && isOntology(ontology) ? ontology : undefined;
|
|
937
1053
|
}
|
|
938
1054
|
function parseIriParts(iri) {
|
|
939
1055
|
const normalized = normalizeIri(iri);
|
|
@@ -1070,7 +1186,17 @@ function pickImportPrefix(namespace, usedPrefixes) {
|
|
|
1070
1186
|
}
|
|
1071
1187
|
return `${candidateBase}${suffix}`;
|
|
1072
1188
|
}
|
|
1073
|
-
function asLiteral(value) {
|
|
1189
|
+
function asLiteral(ontology, value) {
|
|
1190
|
+
if (isTypedQuotedLiteralTransport(value)) {
|
|
1191
|
+
const literalValue = String(value.value ?? '');
|
|
1192
|
+
const datatypeIri = typeof value.datatypeIri === 'string' ? value.datatypeIri.trim() : '';
|
|
1193
|
+
const datatypeRefText = typeof value.datatypeRefText === 'string' ? value.datatypeRefText.trim() : '';
|
|
1194
|
+
return datatypeIri
|
|
1195
|
+
? { $type: 'QuotedLiteral', value: literalValue, type: { $refText: toRefText(ontology, normalizeIri(datatypeIri)) } }
|
|
1196
|
+
: datatypeRefText
|
|
1197
|
+
? { $type: 'QuotedLiteral', value: literalValue, type: { $refText: datatypeRefText } }
|
|
1198
|
+
: { $type: 'QuotedLiteral', value: literalValue };
|
|
1199
|
+
}
|
|
1074
1200
|
if (typeof value === 'boolean') {
|
|
1075
1201
|
return { $type: 'BooleanLiteral', value };
|
|
1076
1202
|
}
|
|
@@ -1082,6 +1208,38 @@ function asLiteral(value) {
|
|
|
1082
1208
|
}
|
|
1083
1209
|
return { $type: 'QuotedLiteral', value: String(value ?? '') };
|
|
1084
1210
|
}
|
|
1211
|
+
async function ensureTypedLiteralDatatypeImport(shared, ontology, value) {
|
|
1212
|
+
if (!isTypedQuotedLiteralTransport(value)) {
|
|
1213
|
+
return;
|
|
1214
|
+
}
|
|
1215
|
+
const datatypeIri = typeof value.datatypeIri === 'string' ? normalizeIri(value.datatypeIri) : '';
|
|
1216
|
+
if (!datatypeIri) {
|
|
1217
|
+
return;
|
|
1218
|
+
}
|
|
1219
|
+
await ensureReferenceImport(shared, ontology, datatypeIri);
|
|
1220
|
+
}
|
|
1221
|
+
function isTypedQuotedLiteralTransport(value) {
|
|
1222
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
1223
|
+
return false;
|
|
1224
|
+
}
|
|
1225
|
+
const record = value;
|
|
1226
|
+
if (record.$type === 'QuotedLiteral') {
|
|
1227
|
+
return true;
|
|
1228
|
+
}
|
|
1229
|
+
return (typeof record.datatypeIri === 'string' || typeof record.datatypeRefText === 'string') && 'value' in record;
|
|
1230
|
+
}
|
|
1231
|
+
function attachAstNode(node, parent, containerProperty) {
|
|
1232
|
+
node.$container = parent;
|
|
1233
|
+
node.$containerProperty = containerProperty;
|
|
1234
|
+
return node;
|
|
1235
|
+
}
|
|
1236
|
+
function pushAstArrayChild(parent, property, node) {
|
|
1237
|
+
if (!Array.isArray(parent[property])) {
|
|
1238
|
+
parent[property] = [];
|
|
1239
|
+
}
|
|
1240
|
+
attachAstNode(node, parent, property);
|
|
1241
|
+
parent[property].push(node);
|
|
1242
|
+
}
|
|
1085
1243
|
function asRequiredIri(value, context) {
|
|
1086
1244
|
if (!isIriLike(value)) {
|
|
1087
1245
|
throw new Error(`Expected IRI for ${context}.`);
|