@skaterqiang/protege-js 0.1.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/CHANGELOG.md +65 -0
- package/LICENSE +48 -0
- package/README.md +287 -0
- package/docs/API.md +654 -0
- package/docs/design/OWL2-/347/274/272/345/217/243/345/210/206/346/236/220.md +140 -0
- package/docs/owl2-rl/OWL2-RL-/350/247/204/345/210/231/347/273/206/345/210/231.md +168 -0
- package/docs/owl2-rl/owl2-profiles-spec-zh.html +1914 -0
- package/docs/owl2-rl/owl2-profiles-spec.html +1916 -0
- package/docs/owl2-rl/rl_rules.json +392 -0
- package/main.js +46 -0
- package/package.json +76 -0
- package/sample/README.md +74 -0
- package/sample/case1-ecommerce-risk.js +170 -0
- package/sample/case10-ecommerce-customer-service.js +454 -0
- package/sample/case2-family-swrl.js +147 -0
- package/sample/case3-pharma-safety.js +132 -0
- package/sample/case4-knowledge-publishing.js +111 -0
- package/sample/case5-obda-profiles.js +153 -0
- package/sample/case6-medical-ontology.js +152 -0
- package/sample/case7-manufacturing-ppr.js +155 -0
- package/sample/case8-real-medical-bfo-ogms.js +353 -0
- package/sample/case9-real-manufacturing-iao.js +360 -0
- package/sample/ontologies/bfo.owl +1715 -0
- package/sample/ontologies/iao.owl +8532 -0
- package/sample/ontologies/ogms.owl +4320 -0
- package/sample/ontologies/ro-core.owl +1010 -0
- package/scripts/verify-api.js +53 -0
- package/src/index.js +176 -0
- package/src/inference/OWL2ProfileReasoners.js +67 -0
- package/src/inference/OWL2RLReasoner.js +65 -0
- package/src/inference/ReasonerQueries.js +111 -0
- package/src/inference/SWRLReasoner.js +409 -0
- package/src/inference/TripleStore.js +82 -0
- package/src/inference/rdf.js +83 -0
- package/src/inference/rules/owl2el.js +33 -0
- package/src/inference/rules/owl2ql.js +29 -0
- package/src/inference/rules/owl2rl.js +823 -0
- package/src/io/FunctionalSyntaxParser.js +399 -0
- package/src/io/FunctionalSyntaxWriter.js +180 -0
- package/src/io/ManchesterSyntaxParser.js +398 -0
- package/src/io/OWLXMLParser.js +356 -0
- package/src/io/OntologyLoader.js +125 -0
- package/src/io/RDFGraphToOntology.js +702 -0
- package/src/io/RDFXMLParser.js +319 -0
- package/src/io/RDFXMLWriter.js +196 -0
- package/src/io/SWRLParser.js +150 -0
- package/src/io/TurtleParser.js +363 -0
- package/src/io/TurtleWriter.js +393 -0
- package/src/model/IRI.js +62 -0
- package/src/model/OWLAxiom.js +507 -0
- package/src/model/OWLClassExpression.js +242 -0
- package/src/model/OWLEntity.js +142 -0
- package/src/model/OWLLiteral.js +30 -0
- package/src/model/OWLModelManager.js +106 -0
- package/src/model/OWLOntology.js +119 -0
- package/src/model/SWRL.js +152 -0
- package/src/model/event/OWLModelManagerEvent.js +33 -0
- package/src/model/hierarchy/HierarchyProvider.js +214 -0
- package/src/profiles/OWL2Profiles.js +185 -0
- package/src/server/public/app.js +97 -0
- package/src/server/public/index.html +49 -0
- package/src/server/webServer.js +138 -0
- package/src/validation/GlobalRestrictionsValidator.js +172 -0
- package/test/core.test.js +111 -0
- package/test/exports-map.test.js +165 -0
- package/test/owl2/axioms.test.js +160 -0
- package/test/owl2/classExpressions.test.js +99 -0
- package/test/owl2/functional-syntax-writer.test.js +65 -0
- package/test/owl2/functional.test.js +113 -0
- package/test/owl2/global-restrictions.test.js +76 -0
- package/test/owl2/longtail.test.js +74 -0
- package/test/owl2/manchester-syntax.test.js +100 -0
- package/test/owl2/ontology-loader-imports.test.js +62 -0
- package/test/owl2/owlxml-parser.test.js +112 -0
- package/test/owl2/profile-reasoners.test.js +108 -0
- package/test/owl2/profiles.test.js +66 -0
- package/test/owl2/rdf-graph-to-ontology.test.js +177 -0
- package/test/owl2/rdfxml-punning.test.js +25 -0
- package/test/owl2/rdfxml-writer.test.js +55 -0
- package/test/owl2/rdfxml.test.js +91 -0
- package/test/owl2/reasoner-queries.test.js +58 -0
- package/test/owl2/sample-e2e.test.js +195 -0
- package/test/owl2/swrl-parser.test.js +60 -0
- package/test/owl2/swrl.test.js +131 -0
- package/test/owl2/turtle-writer.test.js +84 -0
- package/test/owl2/turtle.test.js +124 -0
- package/test/owl2rl/cax.test.js +57 -0
- package/test/owl2rl/cls.test.js +210 -0
- package/test/owl2rl/dt.test.js +72 -0
- package/test/owl2rl/eq.test.js +95 -0
- package/test/owl2rl/prp.test.js +198 -0
- package/test/owl2rl/scm.test.js +203 -0
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// FunctionalSyntaxParser — parses the OWL 2 Functional-Style syntax.
|
|
5
|
+
// Handles the full axiom set: Declaration, SubClassOf, EquivalentClasses,
|
|
6
|
+
// DisjointClasses, DisjointUnion, SubObjectPropertyOf, SubObjectPropertyChain,
|
|
7
|
+
// EquivalentObjectProperties, DisjointObjectProperties, ObjectPropertyDomain,
|
|
8
|
+
// ObjectPropertyRange, InverseObjectProperties, Functional/InverseFunctional/
|
|
9
|
+
// Reflexive/Irreflexive/Symmetric/Asymmetric/Transitive ObjectProperty,
|
|
10
|
+
// SubDataPropertyOf, EquivalentDataProperties, DisjointDataProperties,
|
|
11
|
+
// DataPropertyDomain, DataPropertyRange, FunctionalDataProperty,
|
|
12
|
+
// DatatypeDefinition, HasKey, SameIndividual, DifferentIndividuals,
|
|
13
|
+
// ClassAssertion, ObjectPropertyAssertion, NegativeObjectPropertyAssertion,
|
|
14
|
+
// DataPropertyAssertion, NegativeDataPropertyAssertion,
|
|
15
|
+
// AnnotationAssertion, SubAnnotationPropertyOf, AnnotationPropertyDomain/Range,
|
|
16
|
+
// plus all class expressions (Object*/Data*) and data ranges.
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
|
|
19
|
+
const { OWLOntology, OWLOntologyID } = require('../model/OWLOntology');
|
|
20
|
+
const { OWLClass, OWLObjectProperty, OWLDataProperty, OWLNamedIndividual, OWLDatatype, OWLAnnotationProperty } = require('../model/OWLEntity');
|
|
21
|
+
const { IRI } = require('../model/IRI');
|
|
22
|
+
const { OWLLiteral } = require('../model/OWLLiteral');
|
|
23
|
+
const CE = require('../model/OWLClassExpression');
|
|
24
|
+
const AX = require('../model/OWLAxiom');
|
|
25
|
+
|
|
26
|
+
const KNOWN_PREFIXES = {
|
|
27
|
+
rdf: 'http://www.w3.org/1999/02/22-rdf-syntax-ns#',
|
|
28
|
+
rdfs: 'http://www.w3.org/2000/01/rdf-schema#',
|
|
29
|
+
owl: 'http://www.w3.org/2002/07/owl#',
|
|
30
|
+
xsd: 'http://www.w3.org/2001/XMLSchema#'
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
class FunctionalSyntaxParser {
|
|
34
|
+
constructor() {
|
|
35
|
+
this.prefixes = { ...KNOWN_PREFIXES };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Parse functional-syntax text, return OWLOntology. */
|
|
39
|
+
parse(text, ontologyIRI = 'http://example.org/ontology') {
|
|
40
|
+
const tokens = this._tokenize(text);
|
|
41
|
+
this._pos = 0;
|
|
42
|
+
this._tokens = tokens;
|
|
43
|
+
const onto = new OWLOntology(new OWLOntologyID(IRI.create(ontologyIRI)));
|
|
44
|
+
// Optionally: handle Prefix(...) declarations and Ontology(...) wrapper.
|
|
45
|
+
while (this._pos < tokens.length) {
|
|
46
|
+
this._statement(onto);
|
|
47
|
+
}
|
|
48
|
+
return onto;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
_tokenize(text) {
|
|
52
|
+
const out = [];
|
|
53
|
+
let i = 0;
|
|
54
|
+
const n = text.length;
|
|
55
|
+
while (i < n) {
|
|
56
|
+
const ch = text[i];
|
|
57
|
+
if (/\s/.test(ch)) { i++; continue; }
|
|
58
|
+
if (ch === '#') { while (i < n && text[i] !== '\n') i++; continue; }
|
|
59
|
+
if (ch === '(') { out.push({ t: '(' }); i++; continue; }
|
|
60
|
+
if (ch === ')') { out.push({ t: ')' }); i++; continue; }
|
|
61
|
+
if (ch === '"') {
|
|
62
|
+
let j = i + 1;
|
|
63
|
+
let v = '';
|
|
64
|
+
while (j < n && text[j] !== '"') {
|
|
65
|
+
if (text[j] === '\\' && j + 1 < n) { v += text[j + 1]; j += 2; }
|
|
66
|
+
else { v += text[j]; j++; }
|
|
67
|
+
}
|
|
68
|
+
out.push({ t: 'STRING', v });
|
|
69
|
+
i = j + 1;
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (ch === '<') {
|
|
73
|
+
const j = text.indexOf('>', i);
|
|
74
|
+
out.push({ t: 'IRI', v: text.slice(i + 1, j) });
|
|
75
|
+
i = j + 1;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (ch === '@') {
|
|
79
|
+
let j = i + 1;
|
|
80
|
+
while (j < n && /[A-Za-z-]/.test(text[j])) j++;
|
|
81
|
+
out.push({ t: 'LANG', v: text.slice(i + 1, j) });
|
|
82
|
+
i = j;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (ch === '^' && text[i + 1] === '^') { out.push({ t: '^^' }); i += 2; continue; }
|
|
86
|
+
if (ch === '=') { out.push({ t: '=' }); i++; continue; }
|
|
87
|
+
// number
|
|
88
|
+
if (/[0-9+-]/.test(ch)) {
|
|
89
|
+
let j = i + 1;
|
|
90
|
+
while (j < n && /[0-9.eE+-]/.test(text[j])) j++;
|
|
91
|
+
out.push({ t: 'NUMBER', v: text.slice(i, j) });
|
|
92
|
+
i = j;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
// name (identifier or prefixed)
|
|
96
|
+
let j = i;
|
|
97
|
+
while (j < n && /[A-Za-z0-9_:\-.]/.test(text[j])) j++;
|
|
98
|
+
if (j > i) { out.push({ t: 'NAME', v: text.slice(i, j) }); i = j; continue; }
|
|
99
|
+
throw new Error('Unexpected char: ' + ch + ' at ' + i);
|
|
100
|
+
}
|
|
101
|
+
return out;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
_peek() { return this._tokens[this._pos]; }
|
|
105
|
+
_next() { return this._tokens[this._pos++]; }
|
|
106
|
+
_expect(t) {
|
|
107
|
+
const tok = this._next();
|
|
108
|
+
if (!tok || tok.t !== t) throw new Error(`Expected ${t}, got ${tok && tok.t}`);
|
|
109
|
+
return tok;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
_iriFrom(tok) {
|
|
113
|
+
if (tok.t === 'IRI') return IRI.create(tok.v);
|
|
114
|
+
if (tok.t === 'NAME') {
|
|
115
|
+
const s = tok.v;
|
|
116
|
+
const idx = s.indexOf(':');
|
|
117
|
+
if (idx > 0) {
|
|
118
|
+
const prefix = s.slice(0, idx);
|
|
119
|
+
const local = s.slice(idx + 1);
|
|
120
|
+
if (this.prefixes[prefix]) return IRI.create(this.prefixes[prefix] + local);
|
|
121
|
+
}
|
|
122
|
+
return IRI.create(s);
|
|
123
|
+
}
|
|
124
|
+
throw new Error('Expected IRI, got ' + JSON.stringify(tok));
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
_statement(onto) {
|
|
128
|
+
const tok = this._peek();
|
|
129
|
+
if (tok.t === 'NAME' && tok.v === 'Prefix') {
|
|
130
|
+
this._next(); this._expect('(');
|
|
131
|
+
const pn = this._expect('NAME');
|
|
132
|
+
this._expect('='); // may not tokenize — handle below
|
|
133
|
+
const iriTok = this._expect('IRI');
|
|
134
|
+
const pfx = pn.v.replace(/:$/, '');
|
|
135
|
+
this.prefixes[pfx] = iriTok.v;
|
|
136
|
+
if (onto && onto.addPrefix) onto.addPrefix(pfx, iriTok.v); // prefix fidelity (L5)
|
|
137
|
+
this._expect(')');
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
if (tok.t === 'NAME' && tok.v === 'Ontology') {
|
|
141
|
+
// Ontology( [iri] [versionIRI] Import(...)* Annotation(...)* axiom* )
|
|
142
|
+
this._next(); this._expect('(');
|
|
143
|
+
// Optional ontology IRI
|
|
144
|
+
if (this._peek().t === 'IRI' || (this._peek().t === 'NAME' && this._tokens[this._pos + 1] && this._tokens[this._pos + 1].t !== '(')) {
|
|
145
|
+
onto.id.ontologyIRI = this._iriFrom(this._next());
|
|
146
|
+
// Optional version IRI
|
|
147
|
+
if (this._peek() && this._peek().t === 'IRI') {
|
|
148
|
+
onto.id.versionIRI = this._iriFrom(this._next());
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
while (this._peek() && this._peek().t !== ')') {
|
|
152
|
+
const t = this._peek();
|
|
153
|
+
if (t.t === 'NAME' && t.v === 'Import') {
|
|
154
|
+
this._next(); this._expect('(');
|
|
155
|
+
onto.imports.push(this._iriFrom(this._next()));
|
|
156
|
+
this._expect(')');
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (t.t === 'NAME' && t.v === 'Annotation') {
|
|
160
|
+
// Ontology-level annotation
|
|
161
|
+
this._next(); this._expect('(');
|
|
162
|
+
const propTok = this._next();
|
|
163
|
+
const prop = this._iriFrom(propTok);
|
|
164
|
+
const valTok = this._next();
|
|
165
|
+
let value;
|
|
166
|
+
if (valTok.t === 'STRING') {
|
|
167
|
+
const { OWLLiteral } = require('../model/OWLLiteral');
|
|
168
|
+
value = new OWLLiteral(valTok.v);
|
|
169
|
+
if (this._peek() && this._peek().t === '^^') {
|
|
170
|
+
this._next();
|
|
171
|
+
const { OWLDatatype } = require('../model/OWLEntity');
|
|
172
|
+
value.datatype = new OWLDatatype(this._iriFrom(this._next()));
|
|
173
|
+
}
|
|
174
|
+
} else {
|
|
175
|
+
value = this._iriFrom(valTok);
|
|
176
|
+
}
|
|
177
|
+
const { OWLAnnotationAssertionAxiom } = require('../model/OWLAxiom');
|
|
178
|
+
const { OWLAnnotationProperty } = require('../model/OWLEntity');
|
|
179
|
+
onto.addOntologyAnnotation(new OWLAnnotationAssertionAxiom(
|
|
180
|
+
onto.id.ontologyIRI, new OWLAnnotationProperty(prop), value));
|
|
181
|
+
this._expect(')');
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
this._axiom(onto);
|
|
185
|
+
}
|
|
186
|
+
this._expect(')');
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
this._axiom(onto);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
_axiom(onto) {
|
|
193
|
+
const name = this._expect('NAME').v;
|
|
194
|
+
this._expect('(');
|
|
195
|
+
const args = [];
|
|
196
|
+
while (this._peek() && this._peek().t !== ')') {
|
|
197
|
+
args.push(this._term());
|
|
198
|
+
}
|
|
199
|
+
this._expect(')');
|
|
200
|
+
this._dispatch(onto, name, args);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
_term() {
|
|
204
|
+
const tok = this._peek();
|
|
205
|
+
if (tok.t === '(') {
|
|
206
|
+
this._next();
|
|
207
|
+
const head = this._expect('NAME').v;
|
|
208
|
+
const items = [];
|
|
209
|
+
while (this._peek() && this._peek().t !== ')') items.push(this._term());
|
|
210
|
+
this._expect(')');
|
|
211
|
+
return { kind: 'expr', name: head, items };
|
|
212
|
+
}
|
|
213
|
+
// NAME followed by '(' — e.g. Class(ex:Person) inside Declaration
|
|
214
|
+
if (tok.t === 'NAME' && this._tokens[this._pos + 1] && this._tokens[this._pos + 1].t === '(') {
|
|
215
|
+
const head = this._next().v;
|
|
216
|
+
this._expect('(');
|
|
217
|
+
const items = [];
|
|
218
|
+
while (this._peek() && this._peek().t !== ')') items.push(this._term());
|
|
219
|
+
this._expect(')');
|
|
220
|
+
return { kind: 'expr', name: head, items };
|
|
221
|
+
}
|
|
222
|
+
if (tok.t === 'STRING') {
|
|
223
|
+
this._next();
|
|
224
|
+
let lit = { lex: tok.v, dt: null, lang: null };
|
|
225
|
+
const next = this._peek();
|
|
226
|
+
if (next && next.t === '^^') {
|
|
227
|
+
this._next();
|
|
228
|
+
const dtTok = this._next();
|
|
229
|
+
lit.dt = this._iriFrom(dtTok).toString();
|
|
230
|
+
} else if (next && next.t === 'LANG') {
|
|
231
|
+
this._next();
|
|
232
|
+
lit.lang = next.v;
|
|
233
|
+
}
|
|
234
|
+
return { kind: 'literal', value: lit };
|
|
235
|
+
}
|
|
236
|
+
if (tok.t === 'NUMBER') {
|
|
237
|
+
this._next();
|
|
238
|
+
return { kind: 'number', value: tok.v };
|
|
239
|
+
}
|
|
240
|
+
// IRI or name
|
|
241
|
+
return { kind: 'iri', value: this._iriFrom(this._next()) };
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
_dispatch(onto, name, args) {
|
|
245
|
+
const P = (tok) => {
|
|
246
|
+
if (tok.kind === 'iri') {
|
|
247
|
+
const iri = tok.value;
|
|
248
|
+
// heuristic: ObjectProperty if name in prop position; we let caller wrap.
|
|
249
|
+
return iri;
|
|
250
|
+
}
|
|
251
|
+
return tok;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
const entity = (tok, kind) => {
|
|
255
|
+
const iri = tok.kind === 'iri' ? tok.value : (() => { throw new Error('expected iri'); })();
|
|
256
|
+
switch (kind) {
|
|
257
|
+
case 'class': return new OWLClass(iri);
|
|
258
|
+
case 'op': return new OWLObjectProperty(iri);
|
|
259
|
+
case 'dp': return new OWLDataProperty(iri);
|
|
260
|
+
case 'ni': return new OWLNamedIndividual(iri);
|
|
261
|
+
case 'dt': return new OWLDatatype(iri);
|
|
262
|
+
case 'ap': return new OWLAnnotationProperty(iri);
|
|
263
|
+
default: throw new Error('unknown entity kind ' + kind);
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const literal = (tok) => {
|
|
268
|
+
if (tok.kind !== 'literal' && tok.kind !== 'number') throw new Error('expected literal');
|
|
269
|
+
if (tok.kind === 'number') {
|
|
270
|
+
const v = tok.value;
|
|
271
|
+
const dt = /^-?\d+$/.test(v) ? 'http://www.w3.org/2001/XMLSchema#integer'
|
|
272
|
+
: /^-?\d+\.\d+$/.test(v) ? 'http://www.w3.org/2001/XMLSchema#decimal'
|
|
273
|
+
: 'http://www.w3.org/2001/XMLSchema#double';
|
|
274
|
+
return new OWLLiteral(v, new OWLDatatype(IRI.create(dt)));
|
|
275
|
+
}
|
|
276
|
+
return new OWLLiteral(tok.value.lex, tok.value.dt ? new OWLDatatype(IRI.create(tok.value.dt)) : null, tok.value.lang);
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
const classExpr = (tok) => {
|
|
280
|
+
if (tok.kind === 'iri') return new OWLClass(tok.value);
|
|
281
|
+
const n = tok.name;
|
|
282
|
+
const it = tok.items;
|
|
283
|
+
switch (n) {
|
|
284
|
+
case 'ObjectIntersectionOf': return new CE.OWLObjectIntersectionOf(it.map(classExpr));
|
|
285
|
+
case 'ObjectUnionOf': return new CE.OWLObjectUnionOf(it.map(classExpr));
|
|
286
|
+
case 'ObjectComplementOf': return new CE.OWLObjectComplementOf(classExpr(it[0]));
|
|
287
|
+
case 'ObjectSomeValuesFrom': return new CE.OWLObjectSomeValuesFrom(entity(it[0], 'op'), classExpr(it[1]));
|
|
288
|
+
case 'ObjectAllValuesFrom': return new CE.OWLObjectAllValuesFrom(entity(it[0], 'op'), classExpr(it[1]));
|
|
289
|
+
case 'ObjectHasValue': return new CE.OWLObjectHasValue(entity(it[0], 'op'), entity(it[1], 'ni'));
|
|
290
|
+
case 'ObjectOneOf': return new CE.OWLObjectOneOf(it.map(i => entity(i, 'ni')));
|
|
291
|
+
case 'ObjectHasSelf': return new CE.OWLObjectHasSelf(entity(it[0], 'op'));
|
|
292
|
+
case 'ObjectMinCardinality': return new CE.OWLObjectCardinalityRestriction(CE.ClassExpressionType.OBJECT_MIN_CARDINALITY, parseInt(it[0].value, 10), entity(it[1], 'op'), it[2] ? classExpr(it[2]) : null);
|
|
293
|
+
case 'ObjectMaxCardinality': return new CE.OWLObjectCardinalityRestriction(CE.ClassExpressionType.OBJECT_MAX_CARDINALITY, parseInt(it[0].value, 10), entity(it[1], 'op'), it[2] ? classExpr(it[2]) : null);
|
|
294
|
+
case 'ObjectExactCardinality': return new CE.OWLObjectCardinalityRestriction(CE.ClassExpressionType.OBJECT_EXACT_CARDINALITY, parseInt(it[0].value, 10), entity(it[1], 'op'), it[2] ? classExpr(it[2]) : null);
|
|
295
|
+
case 'DataSomeValuesFrom': return new CE.OWLDataSomeValuesFrom(entity(it[0], 'dp'), dataRange(it[1]));
|
|
296
|
+
case 'DataAllValuesFrom': return new CE.OWLDataAllValuesFrom(entity(it[0], 'dp'), dataRange(it[1]));
|
|
297
|
+
case 'DataHasValue': return new CE.OWLDataHasValue(entity(it[0], 'dp'), literal(it[1]));
|
|
298
|
+
case 'DataMinCardinality': return new CE.OWLDataCardinalityRestriction(CE.ClassExpressionType.DATA_MIN_CARDINALITY, parseInt(it[0].value, 10), entity(it[1], 'dp'), it[2] ? dataRange(it[2]) : null);
|
|
299
|
+
case 'DataMaxCardinality': return new CE.OWLDataCardinalityRestriction(CE.ClassExpressionType.DATA_MAX_CARDINALITY, parseInt(it[0].value, 10), entity(it[1], 'dp'), it[2] ? dataRange(it[2]) : null);
|
|
300
|
+
case 'DataExactCardinality': return new CE.OWLDataCardinalityRestriction(CE.ClassExpressionType.DATA_EXACT_CARDINALITY, parseInt(it[0].value, 10), entity(it[1], 'dp'), it[2] ? dataRange(it[2]) : null);
|
|
301
|
+
default: throw new Error('Unknown class expression: ' + n);
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
const dataRange = (tok) => {
|
|
306
|
+
if (tok.kind === 'iri') return new OWLDatatype(tok.value);
|
|
307
|
+
const n = tok.name;
|
|
308
|
+
const it = tok.items;
|
|
309
|
+
switch (n) {
|
|
310
|
+
case 'DataIntersectionOf': return new CE.OWLDataIntersectionOf(it.map(dataRange));
|
|
311
|
+
case 'DataUnionOf': return new CE.OWLDataUnionOf(it.map(dataRange));
|
|
312
|
+
case 'DataComplementOf': return new CE.OWLDataComplementOf(dataRange(it[0]));
|
|
313
|
+
case 'DataOneOf': return new CE.OWLDataOneOf(it.map(literal));
|
|
314
|
+
case 'DatatypeRestriction': {
|
|
315
|
+
const dt = new OWLDatatype(tok.items[0].value);
|
|
316
|
+
const facets = it.slice(1).map(f => ({ facet: f.items ? f.items[0].value : f.value, value: literal(f.items ? f.items[1] : f) }));
|
|
317
|
+
return new CE.OWLDatatypeRestriction(dt, facets);
|
|
318
|
+
}
|
|
319
|
+
default: throw new Error('Unknown data range: ' + n);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
const add = (ax) => onto.addAxiom(ax);
|
|
324
|
+
|
|
325
|
+
switch (name) {
|
|
326
|
+
case 'Declaration': {
|
|
327
|
+
const entTok = args[0];
|
|
328
|
+
if (entTok.kind === 'expr') {
|
|
329
|
+
const kind = entTok.name;
|
|
330
|
+
const iriTok = entTok.items[0];
|
|
331
|
+
const map = { Class: 'class', ObjectProperty: 'op', DataProperty: 'dp', NamedIndividual: 'ni', Datatype: 'dt', AnnotationProperty: 'ap' };
|
|
332
|
+
if (map[kind]) add(new AX.OWLDeclarationAxiom(entity(iriTok, map[kind])));
|
|
333
|
+
}
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
case 'SubClassOf': add(new AX.OWLSubClassOfAxiom(classExpr(args[0]), classExpr(args[1]))); return;
|
|
337
|
+
case 'EquivalentClasses': add(new AX.OWLEquivalentClassesAxiom(args.map(classExpr))); return;
|
|
338
|
+
case 'DisjointClasses': add(new AX.OWLDisjointClassesAxiom(args.map(classExpr))); return;
|
|
339
|
+
case 'DisjointUnion': add(new AX.OWLDisjointUnionAxiom(entity(args[0], 'class'), args.slice(1).map(classExpr))); return;
|
|
340
|
+
case 'SubObjectPropertyOf': {
|
|
341
|
+
if (args[0] && args[0].kind === 'expr' && args[0].name === 'ObjectPropertyChain') {
|
|
342
|
+
const chain = args[0].items.map(t => entity(t, 'op'));
|
|
343
|
+
add(new AX.OWLSubPropertyChainOfAxiom(chain, entity(args[args.length - 1], 'op')));
|
|
344
|
+
} else {
|
|
345
|
+
add(new AX.OWLSubObjectPropertyOfAxiom(entity(args[0], 'op'), entity(args[1], 'op')));
|
|
346
|
+
}
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
case 'SubObjectPropertyChain': {
|
|
350
|
+
const chain = args[0].kind === 'expr' && args[0].name === 'ObjectPropertyChain'
|
|
351
|
+
? args[0].items.map(t => entity(t, 'op'))
|
|
352
|
+
: args.slice(0, -1).map(t => entity(t, 'op'));
|
|
353
|
+
add(new AX.OWLSubPropertyChainOfAxiom(chain, entity(args[args.length - 1], 'op')));
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
case 'EquivalentObjectProperties': add(new AX.OWLEquivalentObjectPropertiesAxiom(args.map(t => entity(t, 'op')))); return;
|
|
357
|
+
case 'DisjointObjectProperties': add(new AX.OWLDisjointObjectPropertiesAxiom(args.map(t => entity(t, 'op')))); return;
|
|
358
|
+
case 'ObjectPropertyDomain': add(new AX.OWLObjectPropertyDomainAxiom(entity(args[0], 'op'), classExpr(args[1]))); return;
|
|
359
|
+
case 'ObjectPropertyRange': add(new AX.OWLObjectPropertyRangeAxiom(entity(args[0], 'op'), classExpr(args[1]))); return;
|
|
360
|
+
case 'InverseObjectProperties': add(new AX.OWLInverseObjectPropertiesAxiom(entity(args[0], 'op'), entity(args[1], 'op'))); return;
|
|
361
|
+
case 'FunctionalObjectProperty': add(new AX.OWLFunctionalObjectPropertyAxiom(entity(args[0], 'op'))); return;
|
|
362
|
+
case 'InverseFunctionalObjectProperty': add(new AX.OWLInverseFunctionalObjectPropertyAxiom(entity(args[0], 'op'))); return;
|
|
363
|
+
case 'ReflexiveObjectProperty': add(new AX.OWLReflexiveObjectPropertyAxiom(entity(args[0], 'op'))); return;
|
|
364
|
+
case 'IrreflexiveObjectProperty': add(new AX.OWLIrreflexiveObjectPropertyAxiom(entity(args[0], 'op'))); return;
|
|
365
|
+
case 'SymmetricObjectProperty': add(new AX.OWLSymmetricObjectPropertyAxiom(entity(args[0], 'op'))); return;
|
|
366
|
+
case 'AsymmetricObjectProperty': add(new AX.OWLAsymmetricObjectPropertyAxiom(entity(args[0], 'op'))); return;
|
|
367
|
+
case 'TransitiveObjectProperty': add(new AX.OWLTransitiveObjectPropertyAxiom(entity(args[0], 'op'))); return;
|
|
368
|
+
case 'SubDataPropertyOf': add(new AX.OWLSubDataPropertyOfAxiom(entity(args[0], 'dp'), entity(args[1], 'dp'))); return;
|
|
369
|
+
case 'EquivalentDataProperties': add(new AX.OWLEquivalentDataPropertiesAxiom(args.map(t => entity(t, 'dp')))); return;
|
|
370
|
+
case 'DisjointDataProperties': add(new AX.OWLDisjointDataPropertiesAxiom(args.map(t => entity(t, 'dp')))); return;
|
|
371
|
+
case 'DataPropertyDomain': add(new AX.OWLDataPropertyDomainAxiom(entity(args[0], 'dp'), classExpr(args[1]))); return;
|
|
372
|
+
case 'DataPropertyRange': add(new AX.OWLDataPropertyRangeAxiom(entity(args[0], 'dp'), dataRange(args[1]))); return;
|
|
373
|
+
case 'FunctionalDataProperty': add(new AX.OWLFunctionalDataPropertyAxiom(entity(args[0], 'dp'))); return;
|
|
374
|
+
case 'DatatypeDefinition': add(new AX.OWLDatatypeDefinitionAxiom(entity(args[0], 'dt'), dataRange(args[1]))); return;
|
|
375
|
+
case 'HasKey': add(new AX.OWLHasKeyAxiom(classExpr(args[0]), args.slice(1).map(t => entity(t, 'op')))); return;
|
|
376
|
+
case 'SameIndividual': add(new AX.OWLSameIndividualAxiom(args.map(t => entity(t, 'ni')))); return;
|
|
377
|
+
case 'DifferentIndividuals': add(new AX.OWLDifferentIndividualsAxiom(args.map(t => entity(t, 'ni')))); return;
|
|
378
|
+
case 'ClassAssertion': add(new AX.OWLClassAssertionAxiom(entity(args[1], 'ni'), classExpr(args[0]))); return;
|
|
379
|
+
case 'ObjectPropertyAssertion': add(new AX.OWLObjectPropertyAssertionAxiom(entity(args[1], 'ni'), entity(args[0], 'op'), entity(args[2], 'ni'))); return;
|
|
380
|
+
case 'NegativeObjectPropertyAssertion': add(new AX.OWLNegativeObjectPropertyAssertionAxiom(entity(args[1], 'ni'), entity(args[0], 'op'), entity(args[2], 'ni'))); return;
|
|
381
|
+
case 'DataPropertyAssertion': add(new AX.OWLDataPropertyAssertionAxiom(entity(args[1], 'ni'), entity(args[0], 'dp'), literal(args[2]))); return;
|
|
382
|
+
case 'NegativeDataPropertyAssertion': add(new AX.OWLNegativeDataPropertyAssertionAxiom(entity(args[1], 'ni'), entity(args[0], 'dp'), literal(args[2]))); return;
|
|
383
|
+
case 'AnnotationAssertion': {
|
|
384
|
+
const prop = entity(args[0], 'ap');
|
|
385
|
+
const subj = args[1].kind === 'iri' ? args[1].value : null;
|
|
386
|
+
const val = args[2].kind === 'iri' ? args[2].value : literal(args[2]);
|
|
387
|
+
add(new AX.OWLAnnotationAssertionAxiom(subj, prop, val));
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
case 'SubAnnotationPropertyOf': add(new AX.OWLSubAnnotationPropertyOfAxiom(entity(args[0], 'ap'), entity(args[1], 'ap'))); return;
|
|
391
|
+
case 'AnnotationPropertyDomain': add(new AX.OWLAnnotationPropertyDomainAxiom(entity(args[0], 'ap'), args[1].value)); return;
|
|
392
|
+
case 'AnnotationPropertyRange': add(new AX.OWLAnnotationPropertyRangeAxiom(entity(args[0], 'ap'), args[1].value)); return;
|
|
393
|
+
default:
|
|
394
|
+
throw new Error('Unsupported axiom: ' + name);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
module.exports = { FunctionalSyntaxParser };
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// io/FunctionalSyntaxWriter — serialize an OWLOntology to OWL 2 Functional
|
|
5
|
+
// Syntax (W3C §9). Round-trip capable counterpart to FunctionalSyntaxParser.
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
|
|
8
|
+
const { ClassExpressionType: T } = require('../model/OWLClassExpression');
|
|
9
|
+
const { AxiomType: A } = require('../model/OWLAxiom');
|
|
10
|
+
|
|
11
|
+
function iriOf(x) {
|
|
12
|
+
const s = x && x.getIRI ? x.getIRI().toString() : String(x);
|
|
13
|
+
return `<${s}>`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function classExpr(e) {
|
|
17
|
+
if (!e) return '';
|
|
18
|
+
if (e.getIRI) return iriOf(e); // OWLClass / entity
|
|
19
|
+
switch (e.type) {
|
|
20
|
+
case T.OBJECT_INTERSECTION_OF:
|
|
21
|
+
return `ObjectIntersectionOf(${e.operands.map(classExpr).join(' ')})`;
|
|
22
|
+
case T.OBJECT_UNION_OF:
|
|
23
|
+
return `ObjectUnionOf(${e.operands.map(classExpr).join(' ')})`;
|
|
24
|
+
case T.OBJECT_COMPLEMENT_OF:
|
|
25
|
+
return `ObjectComplementOf(${classExpr(e.operand)})`;
|
|
26
|
+
case T.OBJECT_SOME_VALUES_FROM:
|
|
27
|
+
return `ObjectSomeValuesFrom(${iriOf(e.property)} ${classExpr(e.filler)})`;
|
|
28
|
+
case T.OBJECT_ALL_VALUES_FROM:
|
|
29
|
+
return `ObjectAllValuesFrom(${iriOf(e.property)} ${classExpr(e.filler)})`;
|
|
30
|
+
case T.OBJECT_HAS_VALUE:
|
|
31
|
+
return `ObjectHasValue(${iriOf(e.property)} ${iriOf(e.value)})`;
|
|
32
|
+
case T.OBJECT_ONE_OF:
|
|
33
|
+
return `ObjectOneOf(${e.operands.map(iriOf).join(' ')})`;
|
|
34
|
+
case T.OBJECT_HAS_SELF:
|
|
35
|
+
return `ObjectHasSelf(${iriOf(e.property)})`;
|
|
36
|
+
case T.OBJECT_MIN_CARDINALITY:
|
|
37
|
+
return `ObjectMinCardinality(${e.cardinality} ${iriOf(e.property)})`;
|
|
38
|
+
case T.OBJECT_MAX_CARDINALITY:
|
|
39
|
+
return `ObjectMaxCardinality(${e.cardinality} ${iriOf(e.property)})`;
|
|
40
|
+
case T.OBJECT_EXACT_CARDINALITY:
|
|
41
|
+
return `ObjectExactCardinality(${e.cardinality} ${iriOf(e.property)})`;
|
|
42
|
+
case T.OBJECT_MIN_QUALIFIED_CARDINALITY:
|
|
43
|
+
return `ObjectMinCardinality(${e.cardinality} ${iriOf(e.property)} ${classExpr(e.filler)})`;
|
|
44
|
+
case T.OBJECT_MAX_QUALIFIED_CARDINALITY:
|
|
45
|
+
return `ObjectMaxCardinality(${e.cardinality} ${iriOf(e.property)} ${classExpr(e.filler)})`;
|
|
46
|
+
case T.OBJECT_EXACT_QUALIFIED_CARDINALITY:
|
|
47
|
+
return `ObjectExactCardinality(${e.cardinality} ${iriOf(e.property)} ${classExpr(e.filler)})`;
|
|
48
|
+
case T.DATA_SOME_VALUES_FROM:
|
|
49
|
+
return `DataSomeValuesFrom(${iriOf(e.property)} ${dataRange(e.filler)})`;
|
|
50
|
+
case T.DATA_ALL_VALUES_FROM:
|
|
51
|
+
return `DataAllValuesFrom(${iriOf(e.property)} ${dataRange(e.filler)})`;
|
|
52
|
+
case T.DATA_HAS_VALUE:
|
|
53
|
+
return `DataHasValue(${iriOf(e.property)} ${literal(e.value)})`;
|
|
54
|
+
case T.DATA_MIN_CARDINALITY:
|
|
55
|
+
return `DataMinCardinality(${e.cardinality} ${iriOf(e.property)})`;
|
|
56
|
+
case T.DATA_MAX_CARDINALITY:
|
|
57
|
+
return `DataMaxCardinality(${e.cardinality} ${iriOf(e.property)})`;
|
|
58
|
+
case T.DATA_EXACT_CARDINALITY:
|
|
59
|
+
return `DataExactCardinality(${e.cardinality} ${iriOf(e.property)})`;
|
|
60
|
+
default:
|
|
61
|
+
return iriOf(e);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function dataRange(dr) {
|
|
66
|
+
if (!dr) return '';
|
|
67
|
+
if (dr.getIRI) return iriOf(dr); // OWLDatatype
|
|
68
|
+
switch (dr.type) {
|
|
69
|
+
case T.DATA_INTERSECTION_OF:
|
|
70
|
+
return `DataIntersectionOf(${dr.operands.map(dataRange).join(' ')})`;
|
|
71
|
+
case T.DATA_UNION_OF:
|
|
72
|
+
return `DataUnionOf(${dr.operands.map(dataRange).join(' ')})`;
|
|
73
|
+
case T.DATA_COMPLEMENT_OF:
|
|
74
|
+
return `DataComplementOf(${dataRange(dr.operand)})`;
|
|
75
|
+
case T.DATA_ONE_OF:
|
|
76
|
+
return `DataOneOf(${dr.operands.map(literal).join(' ')})`;
|
|
77
|
+
case T.DATATYPE_RESTRICTION: {
|
|
78
|
+
const frs = dr.facetRestrictions.map(f => `${iriOf(f.facet)} ${literal(f.value)}`).join(' ');
|
|
79
|
+
return `DatatypeRestriction(${iriOf(dr.datatype)} ${frs})`;
|
|
80
|
+
}
|
|
81
|
+
default:
|
|
82
|
+
return iriOf(dr);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function literal(l) {
|
|
87
|
+
let s = `"${l.lexicalValue}"`;
|
|
88
|
+
if (l.lang) s += `@${l.lang}`;
|
|
89
|
+
else if (l.datatype) s += `^^${iriOf(l.datatype)}`;
|
|
90
|
+
return s;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function ind(i) {
|
|
94
|
+
return i.isAnonymous && i.isAnonymous() ? i.toString() : iriOf(i);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function axiom(ax) {
|
|
98
|
+
const t = ax.getAxiomType();
|
|
99
|
+
switch (t) {
|
|
100
|
+
case A.DECLARATION: {
|
|
101
|
+
const e = ax.entity;
|
|
102
|
+
const kind = e.isOWLClass() ? 'Class'
|
|
103
|
+
: e.isOWLObjectProperty() ? 'ObjectProperty'
|
|
104
|
+
: e.isOWLDataProperty() ? 'DataProperty'
|
|
105
|
+
: e.isOWLAnnotationProperty() ? 'AnnotationProperty'
|
|
106
|
+
: 'NamedIndividual';
|
|
107
|
+
return `Declaration(${kind}(${iriOf(e)}))`;
|
|
108
|
+
}
|
|
109
|
+
case A.SUBCLASS_OF: return `SubClassOf(${classExpr(ax.subClass)} ${classExpr(ax.superClass)})`;
|
|
110
|
+
case A.EQUIVALENT_CLASSES: return `EquivalentClasses(${ax.classExpressions.map(classExpr).join(' ')})`;
|
|
111
|
+
case A.DISJOINT_CLASSES: return `DisjointClasses(${ax.classExpressions.map(classExpr).join(' ')})`;
|
|
112
|
+
case A.DISJOINT_UNION: return `DisjointUnion(${classExpr(ax.owlClass)} ${ax.classExpressions.map(classExpr).join(' ')})`;
|
|
113
|
+
case A.SUB_OBJECT_PROPERTY_OF: return `SubObjectPropertyOf(${iriOf(ax.subProperty)} ${iriOf(ax.superProperty)})`;
|
|
114
|
+
case A.SUB_DATA_PROPERTY_OF: return `SubDataPropertyOf(${iriOf(ax.subProperty)} ${iriOf(ax.superProperty)})`;
|
|
115
|
+
case A.EQUIVALENT_OBJECT_PROPERTIES: return `EquivalentObjectProperties(${ax.properties.map(iriOf).join(' ')})`;
|
|
116
|
+
case A.DISJOINT_OBJECT_PROPERTIES: return `DisjointObjectProperties(${ax.properties.map(iriOf).join(' ')})`;
|
|
117
|
+
case A.EQUIVALENT_DATA_PROPERTIES: return `EquivalentDataProperties(${ax.properties.map(iriOf).join(' ')})`;
|
|
118
|
+
case A.DISJOINT_DATA_PROPERTIES: return `DisjointDataProperties(${ax.properties.map(iriOf).join(' ')})`;
|
|
119
|
+
case A.INVERSE_OBJECT_PROPERTIES: return `InverseObjectProperties(${iriOf(ax.property1)} ${iriOf(ax.property2)})`;
|
|
120
|
+
case A.OBJECT_PROPERTY_DOMAIN: return `ObjectPropertyDomain(${iriOf(ax.property)} ${classExpr(ax.domain)})`;
|
|
121
|
+
case A.OBJECT_PROPERTY_RANGE: return `ObjectPropertyRange(${iriOf(ax.property)} ${classExpr(ax.range)})`;
|
|
122
|
+
case A.DATA_PROPERTY_DOMAIN: return `DataPropertyDomain(${iriOf(ax.property)} ${classExpr(ax.domain)})`;
|
|
123
|
+
case A.DATA_PROPERTY_RANGE: return `DataPropertyRange(${iriOf(ax.property)} ${dataRange(ax.range)})`;
|
|
124
|
+
case A.FUNCTIONAL_OBJECT_PROPERTY: return `FunctionalObjectProperty(${iriOf(ax.property)})`;
|
|
125
|
+
case A.INVERSE_FUNCTIONAL_OBJECT_PROPERTY: return `InverseFunctionalObjectProperty(${iriOf(ax.property)})`;
|
|
126
|
+
case A.TRANSITIVE_OBJECT_PROPERTY: return `TransitiveObjectProperty(${iriOf(ax.property)})`;
|
|
127
|
+
case A.SYMMETRIC_OBJECT_PROPERTY: return `SymmetricObjectProperty(${iriOf(ax.property)})`;
|
|
128
|
+
case A.ASYMMETRIC_OBJECT_PROPERTY: return `AsymmetricObjectProperty(${iriOf(ax.property)})`;
|
|
129
|
+
case A.REFLEXIVE_OBJECT_PROPERTY: return `ReflexiveObjectProperty(${iriOf(ax.property)})`;
|
|
130
|
+
case A.IRREFLEXIVE_OBJECT_PROPERTY: return `IrreflexiveObjectProperty(${iriOf(ax.property)})`;
|
|
131
|
+
case A.FUNCTIONAL_DATA_PROPERTY: return `FunctionalDataProperty(${iriOf(ax.property)})`;
|
|
132
|
+
case A.SUB_PROPERTY_CHAIN_OF: return `SubObjectPropertyOf(ObjectPropertyChain(${ax.propertyChain.map(iriOf).join(' ')}) ${iriOf(ax.superProperty)})`;
|
|
133
|
+
case A.CLASS_ASSERTION: return `ClassAssertion(${classExpr(ax.classExpression)} ${ind(ax.individual)})`;
|
|
134
|
+
case A.OBJECT_PROPERTY_ASSERTION: return `ObjectPropertyAssertion(${iriOf(ax.property)} ${ind(ax.subject)} ${ind(ax.object)})`;
|
|
135
|
+
case A.DATA_PROPERTY_ASSERTION: return `DataPropertyAssertion(${iriOf(ax.property)} ${ind(ax.subject)} ${literal(ax.literal)})`;
|
|
136
|
+
case A.NEGATIVE_OBJECT_PROPERTY_ASSERTION: return `NegativeObjectPropertyAssertion(${iriOf(ax.property)} ${ind(ax.subject)} ${ind(ax.object)})`;
|
|
137
|
+
case A.NEGATIVE_DATA_PROPERTY_ASSERTION: return `NegativeDataPropertyAssertion(${iriOf(ax.property)} ${ind(ax.subject)} ${literal(ax.literal)})`;
|
|
138
|
+
case A.SAME_INDIVIDUAL: return `SameIndividual(${ax.individuals.map(ind).join(' ')})`;
|
|
139
|
+
case A.DIFFERENT_INDIVIDUALS: return `DifferentIndividuals(${ax.individuals.map(ind).join(' ')})`;
|
|
140
|
+
case A.HAS_KEY: return `HasKey(${classExpr(ax.classExpression)} (${ax.propertyExpressions.map(iriOf).join(' ')}))`;
|
|
141
|
+
case A.ANNOTATION_ASSERTION: {
|
|
142
|
+
const v = ax.value && ax.value.lexicalValue !== undefined ? literal(ax.value) : iriOf(ax.value);
|
|
143
|
+
return `AnnotationAssertion(${iriOf(ax.property)} ${ax.subject ? iriOf(ax.subject) : ''} ${v})`;
|
|
144
|
+
}
|
|
145
|
+
case A.DATATYPE_DEFINITION: return `DatatypeDefinition(${iriOf(ax.datatype)} ${dataRange(ax.dataRange)})`;
|
|
146
|
+
case A.SUB_ANNOTATION_PROPERTY_OF: return `SubAnnotationPropertyOf(${iriOf(ax.subProperty)} ${iriOf(ax.superProperty)})`;
|
|
147
|
+
case A.ANNOTATION_PROPERTY_DOMAIN: return `AnnotationPropertyDomain(${iriOf(ax.property)} ${iriOf(ax.domain)})`;
|
|
148
|
+
case A.ANNOTATION_PROPERTY_RANGE: return `AnnotationPropertyRange(${iriOf(ax.property)} ${iriOf(ax.range)})`;
|
|
149
|
+
default: return null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Serialize an OWLOntology to OWL 2 Functional Syntax.
|
|
155
|
+
* @param {OWLOntology} ont
|
|
156
|
+
* @returns {string}
|
|
157
|
+
*/
|
|
158
|
+
function writeFunctionalSyntax(ont) {
|
|
159
|
+
const lines = [];
|
|
160
|
+
const id = ont.getOntologyID();
|
|
161
|
+
const head = [];
|
|
162
|
+
if (id.ontologyIRI) {
|
|
163
|
+
head.push(iriOf(id.ontologyIRI));
|
|
164
|
+
if (id.versionIRI) head.push(iriOf(id.versionIRI));
|
|
165
|
+
}
|
|
166
|
+
for (const imp of ont.imports || []) {
|
|
167
|
+
head.push(`Import(${iriOf(imp)})`);
|
|
168
|
+
}
|
|
169
|
+
for (const ann of ont.getOntologyAnnotations()) {
|
|
170
|
+
const v = ann.value && ann.value.lexicalValue !== undefined ? literal(ann.value) : iriOf(ann.value);
|
|
171
|
+
head.push(`Annotation(${iriOf(ann.property)} ${v})`);
|
|
172
|
+
}
|
|
173
|
+
const axioms = ont.getAxioms().map(axiom).filter(Boolean);
|
|
174
|
+
lines.push(`Ontology(${head.join(' ')}`);
|
|
175
|
+
for (const a of axioms) lines.push(' ' + a);
|
|
176
|
+
lines.push(')');
|
|
177
|
+
return lines.join('\n');
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
module.exports = { writeFunctionalSyntax, classExpr, dataRange, literal };
|