@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.
Files changed (92) hide show
  1. package/CHANGELOG.md +65 -0
  2. package/LICENSE +48 -0
  3. package/README.md +287 -0
  4. package/docs/API.md +654 -0
  5. package/docs/design/OWL2-/347/274/272/345/217/243/345/210/206/346/236/220.md +140 -0
  6. package/docs/owl2-rl/OWL2-RL-/350/247/204/345/210/231/347/273/206/345/210/231.md +168 -0
  7. package/docs/owl2-rl/owl2-profiles-spec-zh.html +1914 -0
  8. package/docs/owl2-rl/owl2-profiles-spec.html +1916 -0
  9. package/docs/owl2-rl/rl_rules.json +392 -0
  10. package/main.js +46 -0
  11. package/package.json +76 -0
  12. package/sample/README.md +74 -0
  13. package/sample/case1-ecommerce-risk.js +170 -0
  14. package/sample/case10-ecommerce-customer-service.js +454 -0
  15. package/sample/case2-family-swrl.js +147 -0
  16. package/sample/case3-pharma-safety.js +132 -0
  17. package/sample/case4-knowledge-publishing.js +111 -0
  18. package/sample/case5-obda-profiles.js +153 -0
  19. package/sample/case6-medical-ontology.js +152 -0
  20. package/sample/case7-manufacturing-ppr.js +155 -0
  21. package/sample/case8-real-medical-bfo-ogms.js +353 -0
  22. package/sample/case9-real-manufacturing-iao.js +360 -0
  23. package/sample/ontologies/bfo.owl +1715 -0
  24. package/sample/ontologies/iao.owl +8532 -0
  25. package/sample/ontologies/ogms.owl +4320 -0
  26. package/sample/ontologies/ro-core.owl +1010 -0
  27. package/scripts/verify-api.js +53 -0
  28. package/src/index.js +176 -0
  29. package/src/inference/OWL2ProfileReasoners.js +67 -0
  30. package/src/inference/OWL2RLReasoner.js +65 -0
  31. package/src/inference/ReasonerQueries.js +111 -0
  32. package/src/inference/SWRLReasoner.js +409 -0
  33. package/src/inference/TripleStore.js +82 -0
  34. package/src/inference/rdf.js +83 -0
  35. package/src/inference/rules/owl2el.js +33 -0
  36. package/src/inference/rules/owl2ql.js +29 -0
  37. package/src/inference/rules/owl2rl.js +823 -0
  38. package/src/io/FunctionalSyntaxParser.js +399 -0
  39. package/src/io/FunctionalSyntaxWriter.js +180 -0
  40. package/src/io/ManchesterSyntaxParser.js +398 -0
  41. package/src/io/OWLXMLParser.js +356 -0
  42. package/src/io/OntologyLoader.js +125 -0
  43. package/src/io/RDFGraphToOntology.js +702 -0
  44. package/src/io/RDFXMLParser.js +319 -0
  45. package/src/io/RDFXMLWriter.js +196 -0
  46. package/src/io/SWRLParser.js +150 -0
  47. package/src/io/TurtleParser.js +363 -0
  48. package/src/io/TurtleWriter.js +393 -0
  49. package/src/model/IRI.js +62 -0
  50. package/src/model/OWLAxiom.js +507 -0
  51. package/src/model/OWLClassExpression.js +242 -0
  52. package/src/model/OWLEntity.js +142 -0
  53. package/src/model/OWLLiteral.js +30 -0
  54. package/src/model/OWLModelManager.js +106 -0
  55. package/src/model/OWLOntology.js +119 -0
  56. package/src/model/SWRL.js +152 -0
  57. package/src/model/event/OWLModelManagerEvent.js +33 -0
  58. package/src/model/hierarchy/HierarchyProvider.js +214 -0
  59. package/src/profiles/OWL2Profiles.js +185 -0
  60. package/src/server/public/app.js +97 -0
  61. package/src/server/public/index.html +49 -0
  62. package/src/server/webServer.js +138 -0
  63. package/src/validation/GlobalRestrictionsValidator.js +172 -0
  64. package/test/core.test.js +111 -0
  65. package/test/exports-map.test.js +165 -0
  66. package/test/owl2/axioms.test.js +160 -0
  67. package/test/owl2/classExpressions.test.js +99 -0
  68. package/test/owl2/functional-syntax-writer.test.js +65 -0
  69. package/test/owl2/functional.test.js +113 -0
  70. package/test/owl2/global-restrictions.test.js +76 -0
  71. package/test/owl2/longtail.test.js +74 -0
  72. package/test/owl2/manchester-syntax.test.js +100 -0
  73. package/test/owl2/ontology-loader-imports.test.js +62 -0
  74. package/test/owl2/owlxml-parser.test.js +112 -0
  75. package/test/owl2/profile-reasoners.test.js +108 -0
  76. package/test/owl2/profiles.test.js +66 -0
  77. package/test/owl2/rdf-graph-to-ontology.test.js +177 -0
  78. package/test/owl2/rdfxml-punning.test.js +25 -0
  79. package/test/owl2/rdfxml-writer.test.js +55 -0
  80. package/test/owl2/rdfxml.test.js +91 -0
  81. package/test/owl2/reasoner-queries.test.js +58 -0
  82. package/test/owl2/sample-e2e.test.js +195 -0
  83. package/test/owl2/swrl-parser.test.js +60 -0
  84. package/test/owl2/swrl.test.js +131 -0
  85. package/test/owl2/turtle-writer.test.js +84 -0
  86. package/test/owl2/turtle.test.js +124 -0
  87. package/test/owl2rl/cax.test.js +57 -0
  88. package/test/owl2rl/cls.test.js +210 -0
  89. package/test/owl2rl/dt.test.js +72 -0
  90. package/test/owl2rl/eq.test.js +95 -0
  91. package/test/owl2rl/prp.test.js +198 -0
  92. package/test/owl2rl/scm.test.js +203 -0
@@ -0,0 +1,160 @@
1
+ 'use strict';
2
+
3
+ const { test } = require('node:test');
4
+ const assert = require('node:assert');
5
+ const AX = require('../../src/model/OWLAxiom');
6
+ const {
7
+ OWLClass, OWLObjectProperty, OWLDataProperty, OWLNamedIndividual,
8
+ OWLDatatype, OWLAnnotationProperty
9
+ } = require('../../src/model/OWLEntity');
10
+ const { IRI } = require('../../src/model/IRI');
11
+ const { OWLLiteral } = require('../../src/model/OWLLiteral');
12
+
13
+ const ex = (s) => IRI.create('http://example.org/' + s);
14
+ const cls = (s) => new OWLClass(ex(s));
15
+ const op = (s) => new OWLObjectProperty(ex(s));
16
+ const dp = (s) => new OWLDataProperty(ex(s));
17
+ const ni = (s) => new OWLNamedIndividual(ex(s));
18
+ const ap = (s) => new OWLAnnotationProperty(ex(s));
19
+ const dt = (s) => new OWLDatatype(ex(s));
20
+
21
+ test('OWLDisjointUnionAxiom', () => {
22
+ const ax = new AX.OWLDisjointUnionAxiom(cls('Color'), [cls('Red'), cls('Green'), cls('Blue')]);
23
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.DISJOINT_UNION);
24
+ assert.strictEqual(ax.classExpressions.length, 3);
25
+ assert.match(ax.toString(), /DisjointUnion|union/);
26
+ });
27
+
28
+ test('OWLSubPropertyChainOfAxiom', () => {
29
+ const ax = new AX.OWLSubPropertyChainOfAxiom([op('hasParent'), op('hasBrother')], op('hasUncle'));
30
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.SUB_PROPERTY_CHAIN_OF);
31
+ assert.strictEqual(ax.propertyChain.length, 2);
32
+ assert.match(ax.toString(), /SubObjectPropertyChain|SubPropertyChain|→|∘/);
33
+ });
34
+
35
+ test('OWLEquivalentObjectPropertiesAxiom', () => {
36
+ const ax = new AX.OWLEquivalentObjectPropertiesAxiom([op('hasFather'), op('hasDad')]);
37
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.EQUIVALENT_OBJECT_PROPERTIES);
38
+ assert.strictEqual(ax.properties.length, 2);
39
+ });
40
+
41
+ test('OWLDisjointObjectPropertiesAxiom', () => {
42
+ const ax = new AX.OWLDisjointObjectPropertiesAxiom([op('hasParent'), op('hasChild')]);
43
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.DISJOINT_OBJECT_PROPERTIES);
44
+ assert.strictEqual(ax.properties.length, 2);
45
+ });
46
+
47
+ test('OWLEquivalentDataPropertiesAxiom', () => {
48
+ const ax = new AX.OWLEquivalentDataPropertiesAxiom([dp('age'), dp('years')]);
49
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.EQUIVALENT_DATA_PROPERTIES);
50
+ assert.strictEqual(ax.properties.length, 2);
51
+ });
52
+
53
+ test('OWLDisjointDataPropertiesAxiom', () => {
54
+ const ax = new AX.OWLDisjointDataPropertiesAxiom([dp('name'), dp('ssn')]);
55
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.DISJOINT_DATA_PROPERTIES);
56
+ });
57
+
58
+ test('OWLDataPropertyRangeAxiom', () => {
59
+ const ax = new AX.OWLDataPropertyRangeAxiom(dp('age'), dt('integer'));
60
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.DATA_PROPERTY_RANGE);
61
+ assert.strictEqual(ax.range.getIRI().toString(), ex('integer').toString());
62
+ });
63
+
64
+ test('OWLDatatypeDefinitionAxiom', () => {
65
+ const ax = new AX.OWLDatatypeDefinitionAxiom(dt('Age'), dt('integer'));
66
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.DATATYPE_DEFINITION);
67
+ });
68
+
69
+ test('OWLHasKeyAxiom', () => {
70
+ const ax = new AX.OWLHasKeyAxiom(cls('Person'), [op('hasSSN'), dp('ssn')]);
71
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.HAS_KEY);
72
+ assert.strictEqual(ax.propertyExpressions.length, 2);
73
+ });
74
+
75
+ test('OWLSameIndividualAxiom', () => {
76
+ const ax = new AX.OWLSameIndividualAxiom([ni('alice'), ni('alicia')]);
77
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.SAME_INDIVIDUAL);
78
+ assert.strictEqual(ax.individuals.length, 2);
79
+ });
80
+
81
+ test('OWLDifferentIndividualsAxiom', () => {
82
+ const ax = new AX.OWLDifferentIndividualsAxiom([ni('alice'), ni('bob')]);
83
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.DIFFERENT_INDIVIDUALS);
84
+ });
85
+
86
+ test('OWLNegativeObjectPropertyAssertionAxiom', () => {
87
+ const ax = new AX.OWLNegativeObjectPropertyAssertionAxiom(ni('alice'), op('knows'), ni('bob'));
88
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.NEGATIVE_OBJECT_PROPERTY_ASSERTION);
89
+ });
90
+
91
+ test('OWLNegativeDataPropertyAssertionAxiom', () => {
92
+ const lit = new OWLLiteral('30', dt('integer'));
93
+ const ax = new AX.OWLNegativeDataPropertyAssertionAxiom(ni('alice'), dp('age'), lit);
94
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.NEGATIVE_DATA_PROPERTY_ASSERTION);
95
+ });
96
+
97
+ test('OWLSubAnnotationPropertyOfAxiom', () => {
98
+ const ax = new AX.OWLSubAnnotationPropertyOfAxiom(ap('label'), ap('title'));
99
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.SUB_ANNOTATION_PROPERTY_OF);
100
+ });
101
+
102
+ test('OWLAnnotationPropertyDomainAxiom', () => {
103
+ const ax = new AX.OWLAnnotationPropertyDomainAxiom(ap('label'), ex('Thing'));
104
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.ANNOTATION_PROPERTY_DOMAIN);
105
+ });
106
+
107
+ test('OWLAnnotationPropertyRangeAxiom', () => {
108
+ const ax = new AX.OWLAnnotationPropertyRangeAxiom(ap('label'), ex('String'));
109
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.ANNOTATION_PROPERTY_RANGE);
110
+ });
111
+
112
+ test('OWLFunctionalObjectPropertyAxiom', () => {
113
+ const ax = new AX.OWLFunctionalObjectPropertyAxiom(op('hasMother'));
114
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.FUNCTIONAL_OBJECT_PROPERTY);
115
+ });
116
+
117
+ test('OWLInverseFunctionalObjectPropertyAxiom', () => {
118
+ const ax = new AX.OWLInverseFunctionalObjectPropertyAxiom(op('isMotherOf'));
119
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.INVERSE_FUNCTIONAL_OBJECT_PROPERTY);
120
+ });
121
+
122
+ test('OWLReflexiveObjectPropertyAxiom', () => {
123
+ const ax = new AX.OWLReflexiveObjectPropertyAxiom(op('knows'));
124
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.REFLEXIVE_OBJECT_PROPERTY);
125
+ });
126
+
127
+ test('OWLIrreflexiveObjectPropertyAxiom', () => {
128
+ const ax = new AX.OWLIrreflexiveObjectPropertyAxiom(op('isParentOf'));
129
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.IRREFLEXIVE_OBJECT_PROPERTY);
130
+ });
131
+
132
+ test('OWLSymmetricObjectPropertyAxiom', () => {
133
+ const ax = new AX.OWLSymmetricObjectPropertyAxiom(op('isSiblingOf'));
134
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.SYMMETRIC_OBJECT_PROPERTY);
135
+ });
136
+
137
+ test('OWLAsymmetricObjectPropertyAxiom', () => {
138
+ const ax = new AX.OWLAsymmetricObjectPropertyAxiom(op('isParentOf'));
139
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.ASYMMETRIC_OBJECT_PROPERTY);
140
+ });
141
+
142
+ test('OWLTransitiveObjectPropertyAxiom', () => {
143
+ const ax = new AX.OWLTransitiveObjectPropertyAxiom(op('hasAncestor'));
144
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.TRANSITIVE_OBJECT_PROPERTY);
145
+ });
146
+
147
+ test('OWLFunctionalDataPropertyAxiom', () => {
148
+ const ax = new AX.OWLFunctionalDataPropertyAxiom(dp('age'));
149
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.FUNCTIONAL_DATA_PROPERTY);
150
+ });
151
+
152
+ test('OWLInverseObjectPropertiesAxiom', () => {
153
+ const ax = new AX.OWLInverseObjectPropertiesAxiom(op('hasParent'), op('hasChild'));
154
+ assert.strictEqual(ax.getAxiomType(), AX.AxiomType.INVERSE_OBJECT_PROPERTIES);
155
+ });
156
+
157
+ test('AxiomType has 38 entries', () => {
158
+ const keys = Object.keys(AX.AxiomType);
159
+ assert.strictEqual(keys.length, 38);
160
+ });
@@ -0,0 +1,99 @@
1
+ 'use strict';
2
+
3
+ const { test } = require('node:test');
4
+ const assert = require('node:assert');
5
+ const CE = require('../../src/model/OWLClassExpression');
6
+ const {
7
+ OWLClass, OWLObjectProperty, OWLDataProperty, OWLNamedIndividual, OWLDatatype
8
+ } = require('../../src/model/OWLEntity');
9
+ const { IRI } = require('../../src/model/IRI');
10
+ const { OWLLiteral } = require('../../src/model/OWLLiteral');
11
+
12
+ const ex = (s) => IRI.create('http://example.org/' + s);
13
+ const cls = (s) => new OWLClass(ex(s));
14
+ const op = (s) => new OWLObjectProperty(ex(s));
15
+ const dp = (s) => new OWLDataProperty(ex(s));
16
+ const ni = (s) => new OWLNamedIndividual(ex(s));
17
+ const dt = (s) => new OWLDatatype(ex(s));
18
+
19
+ test('OWLObjectHasSelf', () => {
20
+ const e = new CE.OWLObjectHasSelf(op('likes'));
21
+ assert.strictEqual(e.type, CE.ClassExpressionType.OBJECT_HAS_SELF);
22
+ assert.match(e.toString(), /Self/);
23
+ });
24
+
25
+ test('OWLDataSomeValuesFrom', () => {
26
+ const e = new CE.OWLDataSomeValuesFrom(dp('age'), dt('integer'));
27
+ assert.strictEqual(e.type, CE.ClassExpressionType.DATA_SOME_VALUES_FROM);
28
+ });
29
+
30
+ test('OWLDataAllValuesFrom', () => {
31
+ const e = new CE.OWLDataAllValuesFrom(dp('age'), dt('integer'));
32
+ assert.strictEqual(e.type, CE.ClassExpressionType.DATA_ALL_VALUES_FROM);
33
+ });
34
+
35
+ test('OWLDataHasValue', () => {
36
+ const lit = new OWLLiteral('30', dt('integer'));
37
+ const e = new CE.OWLDataHasValue(dp('age'), lit);
38
+ assert.strictEqual(e.type, CE.ClassExpressionType.DATA_HAS_VALUE);
39
+ });
40
+
41
+ test('OWLDataMinCardinality', () => {
42
+ const e = new CE.OWLDataCardinalityRestriction(CE.ClassExpressionType.DATA_MIN_CARDINALITY, 1, dp('age'), null);
43
+ assert.strictEqual(e.type, CE.ClassExpressionType.DATA_MIN_CARDINALITY);
44
+ assert.strictEqual(e.cardinality, 1);
45
+ });
46
+
47
+ test('OWLDataMaxCardinality', () => {
48
+ const e = new CE.OWLDataCardinalityRestriction(CE.ClassExpressionType.DATA_MAX_CARDINALITY, 5, dp('email'), null);
49
+ assert.strictEqual(e.type, CE.ClassExpressionType.DATA_MAX_CARDINALITY);
50
+ assert.strictEqual(e.cardinality, 5);
51
+ });
52
+
53
+ test('OWLDataExactCardinality', () => {
54
+ const e = new CE.OWLDataCardinalityRestriction(CE.ClassExpressionType.DATA_EXACT_CARDINALITY, 2, dp('phone'), dt('string'));
55
+ assert.strictEqual(e.type, CE.ClassExpressionType.DATA_EXACT_CARDINALITY);
56
+ });
57
+
58
+ test('OWLDataIntersectionOf', () => {
59
+ const e = new CE.OWLDataIntersectionOf([dt('integer'), dt('nonNegativeInteger')]);
60
+ assert.strictEqual(e.type, CE.ClassExpressionType.DATA_INTERSECTION_OF);
61
+ });
62
+
63
+ test('OWLDataUnionOf', () => {
64
+ const e = new CE.OWLDataUnionOf([dt('string'), dt('integer')]);
65
+ assert.strictEqual(e.type, CE.ClassExpressionType.DATA_UNION_OF);
66
+ });
67
+
68
+ test('OWLDataComplementOf', () => {
69
+ const e = new CE.OWLDataComplementOf(dt('string'));
70
+ assert.strictEqual(e.type, CE.ClassExpressionType.DATA_COMPLEMENT_OF);
71
+ });
72
+
73
+ test('OWLDataOneOf', () => {
74
+ const lits = [new OWLLiteral('a', dt('string')), new OWLLiteral('b', dt('string'))];
75
+ const e = new CE.OWLDataOneOf(lits);
76
+ assert.strictEqual(e.type, CE.ClassExpressionType.DATA_ONE_OF);
77
+ assert.strictEqual(e.operands.length, 2);
78
+ });
79
+
80
+ test('OWLDatatypeRestriction with facets', () => {
81
+ const e = new CE.OWLDatatypeRestriction(dt('integer'), [
82
+ { facet: ex('minInclusive'), value: new OWLLiteral('0', dt('integer')) },
83
+ { facet: ex('maxInclusive'), value: new OWLLiteral('120', dt('integer')) }
84
+ ]);
85
+ assert.strictEqual(e.type, CE.ClassExpressionType.DATATYPE_RESTRICTION);
86
+ assert.strictEqual(e.facetRestrictions.length, 2);
87
+ });
88
+
89
+ test('OWLObjectMinCardinality qualified', () => {
90
+ const e = new CE.OWLObjectCardinalityRestriction(CE.ClassExpressionType.OBJECT_MIN_CARDINALITY, 2, op('hasChild'), cls('Person'));
91
+ assert.strictEqual(e.type, CE.ClassExpressionType.OBJECT_MIN_CARDINALITY);
92
+ assert.strictEqual(e.cardinality, 2);
93
+ assert.ok(e.filler);
94
+ });
95
+
96
+ test('ClassExpressionType has 26 entries', () => {
97
+ const keys = Object.keys(CE.ClassExpressionType);
98
+ assert.strictEqual(keys.length, 26);
99
+ });
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+
3
+ const test = require('node:test');
4
+ const assert = require('node:assert/strict');
5
+
6
+ const { writeFunctionalSyntax } = require('../../src/io/FunctionalSyntaxWriter');
7
+ const { FunctionalSyntaxParser } = require('../../src/io/FunctionalSyntaxParser');
8
+ const { OWLOntology, OWLOntologyID } = require('../../src/model/OWLOntology');
9
+ const { OWLClass, OWLObjectProperty, OWLNamedIndividual } = require('../../src/model/OWLEntity');
10
+ const {
11
+ OWLDeclarationAxiom, OWLSubClassOfAxiom, OWLClassAssertionAxiom,
12
+ OWLObjectPropertyAssertionAxiom
13
+ } = require('../../src/model/OWLAxiom');
14
+ const { OWLObjectSomeValuesFrom } = require('../../src/model/OWLClassExpression');
15
+ const { IRI } = require('../../src/model/IRI');
16
+
17
+ const EX = 'http://ex.org/';
18
+
19
+ test('write declarations + subClassOf, round-trip parse', () => {
20
+ const ont = new OWLOntology(new OWLOntologyID(IRI.create(EX)));
21
+ ont.addAxiom(new OWLDeclarationAxiom(new OWLClass(EX + 'A')));
22
+ ont.addAxiom(new OWLDeclarationAxiom(new OWLClass(EX + 'B')));
23
+ ont.addAxiom(new OWLSubClassOfAxiom(new OWLClass(EX + 'A'), new OWLClass(EX + 'B')));
24
+
25
+ const text = writeFunctionalSyntax(ont);
26
+ assert.match(text, /Ontology\(/);
27
+ assert.match(text, /Declaration\(Class\(<http:\/\/ex\.org\/A>\)\)/);
28
+ assert.match(text, /SubClassOf\(<http:\/\/ex\.org\/A> <http:\/\/ex\.org\/B>\)/);
29
+
30
+ // Round-trip
31
+ const parsed = new FunctionalSyntaxParser().parse(text, EX);
32
+ assert.equal(parsed.getAxiomsOfType('SubClassOf').length, 1);
33
+ assert.equal(parsed.getAxiomsOfType('Declaration').length, 2);
34
+ });
35
+
36
+ test('write nested class expression (someValuesFrom)', () => {
37
+ const ont = new OWLOntology(new OWLOntologyID(IRI.create(EX)));
38
+ const p = new OWLObjectProperty(EX + 'p');
39
+ const filler = new OWLClass(EX + 'B');
40
+ const ce = new OWLObjectSomeValuesFrom(p, filler);
41
+ ont.addAxiom(new OWLSubClassOfAxiom(new OWLClass(EX + 'A'), ce));
42
+
43
+ const text = writeFunctionalSyntax(ont);
44
+ assert.match(text, /ObjectSomeValuesFrom\(<http:\/\/ex\.org\/p> <http:\/\/ex\.org\/B>\)/);
45
+ });
46
+
47
+ test('write class assertion + property assertion', () => {
48
+ const ont = new OWLOntology(new OWLOntologyID(IRI.create(EX)));
49
+ const i = new OWLNamedIndividual(EX + 'i');
50
+ const j = new OWLNamedIndividual(EX + 'j');
51
+ const p = new OWLObjectProperty(EX + 'p');
52
+ ont.addAxiom(new OWLClassAssertionAxiom(i, new OWLClass(EX + 'C')));
53
+ ont.addAxiom(new OWLObjectPropertyAssertionAxiom(i, p, j));
54
+
55
+ const text = writeFunctionalSyntax(ont);
56
+ assert.match(text, /ClassAssertion\(<http:\/\/ex\.org\/C> <http:\/\/ex\.org\/i>\)/);
57
+ assert.match(text, /ObjectPropertyAssertion\(<http:\/\/ex\.org\/p> <http:\/\/ex\.org\/i> <http:\/\/ex\.org\/j>\)/);
58
+ });
59
+
60
+ test('write ontology header with imports', () => {
61
+ const ont = new OWLOntology(new OWLOntologyID(IRI.create(EX)));
62
+ ont.imports.push('http://other.org/ont');
63
+ const text = writeFunctionalSyntax(ont);
64
+ assert.match(text, /Import\(<http:\/\/other\.org\/ont>\)/);
65
+ });
@@ -0,0 +1,113 @@
1
+ 'use strict';
2
+
3
+ const { test } = require('node:test');
4
+ const assert = require('node:assert');
5
+ const { FunctionalSyntaxParser } = require('../../src/io/FunctionalSyntaxParser');
6
+
7
+ const parse = (text) => new FunctionalSyntaxParser().parse(text);
8
+
9
+ test('Functional: Declaration Class', () => {
10
+ const o = parse('Declaration(Class(<http://example.org/Person>))');
11
+ assert.strictEqual(o.getAxiomCount(), 1);
12
+ const ax = o.getAxioms()[0];
13
+ assert.strictEqual(ax.getAxiomType(), 'Declaration');
14
+ });
15
+
16
+ test('Functional: SubClassOf', () => {
17
+ const o = parse('SubClassOf(<http://example.org/Student> <http://example.org/Person>)');
18
+ assert.strictEqual(o.getAxiomCount(), 1);
19
+ assert.match(o.getAxioms()[0].toString(), /SubClassOf/);
20
+ });
21
+
22
+ test('Functional: EquivalentClasses', () => {
23
+ const o = parse('EquivalentClasses(<http://example.org/Person> <http://example.org/Human>)');
24
+ assert.strictEqual(o.getAxiomCount(), 1);
25
+ });
26
+
27
+ test('Functional: DisjointClasses', () => {
28
+ const o = parse('DisjointClasses(<http://example.org/Cat> <http://example.org/Dog>)');
29
+ assert.strictEqual(o.getAxiomCount(), 1);
30
+ });
31
+
32
+ test('Functional: DisjointUnion', () => {
33
+ const o = parse('DisjointUnion(<http://example.org/Color> <http://example.org/R> <http://example.org/G>)');
34
+ assert.strictEqual(o.getAxiomCount(), 1);
35
+ assert.match(o.getAxioms()[0].toString(), /DisjointUnion/);
36
+ });
37
+
38
+ test('Functional: SubObjectPropertyChain', () => {
39
+ const o = parse('SubObjectPropertyOf(ObjectPropertyChain(<http://example.org/hasParent> <http://example.org/hasBrother>) <http://example.org/hasUncle>)');
40
+ assert.strictEqual(o.getAxiomCount(), 1);
41
+ assert.match(o.getAxioms()[0].toString(), /Chain/);
42
+ });
43
+
44
+ test('Functional: TransitiveObjectProperty', () => {
45
+ const o = parse('TransitiveObjectProperty(<http://example.org/hasAncestor>)');
46
+ assert.strictEqual(o.getAxiomCount(), 1);
47
+ });
48
+
49
+ test('Functional: ClassAssertion', () => {
50
+ const o = parse('ClassAssertion(<http://example.org/Person> <http://example.org/alice>)');
51
+ assert.strictEqual(o.getAxiomCount(), 1);
52
+ });
53
+
54
+ test('Functional: ObjectPropertyAssertion', () => {
55
+ const o = parse('ObjectPropertyAssertion(<http://example.org/knows> <http://example.org/a> <http://example.org/b>)');
56
+ assert.strictEqual(o.getAxiomCount(), 1);
57
+ });
58
+
59
+ test('Functional: DataPropertyAssertion with typed literal', () => {
60
+ const o = parse('Prefix(xsd:=<http://www.w3.org/2001/XMLSchema#>) DataPropertyAssertion(<http://example.org/age> <http://example.org/a> "30"^^xsd:integer)');
61
+ assert.strictEqual(o.getAxiomCount(), 1);
62
+ });
63
+
64
+ test('Functional: HasKey', () => {
65
+ const o = parse('HasKey(<http://example.org/Person> <http://example.org/ssn>)');
66
+ assert.strictEqual(o.getAxiomCount(), 1);
67
+ assert.match(o.getAxioms()[0].toString(), /HasKey/);
68
+ });
69
+
70
+ test('Functional: SameIndividual / DifferentIndividuals', () => {
71
+ const o = parse('SameIndividual(<http://example.org/a> <http://example.org/b>) DifferentIndividuals(<http://example.org/c> <http://example.org/d>)');
72
+ assert.strictEqual(o.getAxiomCount(), 2);
73
+ });
74
+
75
+ test('Functional: Ontology wrapper', () => {
76
+ const o = parse(`
77
+ Ontology(<http://example.org/ont>
78
+ Declaration(Class(<http://example.org/Person>))
79
+ SubClassOf(<http://example.org/Student> <http://example.org/Person>)
80
+ )
81
+ `);
82
+ assert.strictEqual(o.getAxiomCount(), 2);
83
+ });
84
+
85
+ test('Functional: class expressions', () => {
86
+ const o = parse(`
87
+ SubClassOf(<http://example.org/A> ObjectIntersectionOf(<http://example.org/B> <http://example.org/C>))
88
+ `);
89
+ assert.strictEqual(o.getAxiomCount(), 1);
90
+ assert.match(o.getAxioms()[0].toString(), /and|Intersection|∩/);
91
+ });
92
+
93
+ test('Functional: DataSomeValuesFrom', () => {
94
+ const o = parse(`
95
+ SubClassOf(<http://example.org/Person> DataSomeValuesFrom(<http://example.org/age> <http://www.w3.org/2001/XMLSchema#integer>))
96
+ `);
97
+ assert.strictEqual(o.getAxiomCount(), 1);
98
+ });
99
+
100
+ test('Functional: NegativeObjectPropertyAssertion', () => {
101
+ const o = parse('NegativeObjectPropertyAssertion(<http://example.org/knows> <http://example.org/a> <http://example.org/b>)');
102
+ assert.strictEqual(o.getAxiomCount(), 1);
103
+ });
104
+
105
+ test('Functional: AnnotationAssertion', () => {
106
+ const o = parse('AnnotationAssertion(<http://www.w3.org/2000/01/rdf-schema#label> <http://example.org/Thing> "A thing")');
107
+ assert.strictEqual(o.getAxiomCount(), 1);
108
+ });
109
+
110
+ test('Functional: DatatypeDefinition', () => {
111
+ const o = parse('DatatypeDefinition(<http://example.org/Age> <http://www.w3.org/2001/XMLSchema#integer>)');
112
+ assert.strictEqual(o.getAxiomCount(), 1);
113
+ });
@@ -0,0 +1,76 @@
1
+ 'use strict';
2
+
3
+ const test = require('node:test');
4
+ const assert = require('node:assert/strict');
5
+
6
+ const { GlobalRestrictionsValidator } = require('../../src/validation/GlobalRestrictionsValidator');
7
+ const { OWLOntology, OWLOntologyID } = require('../../src/model/OWLOntology');
8
+ const { OWLClass, OWLObjectProperty, OWLNamedIndividual } = require('../../src/model/OWLEntity');
9
+ const {
10
+ OWLSubPropertyChainOfAxiom, OWLFunctionalObjectPropertyAxiom,
11
+ OWLIrreflexiveObjectPropertyAxiom, OWLClassAssertionAxiom,
12
+ OWLSubClassOfAxiom
13
+ } = require('../../src/model/OWLAxiom');
14
+ const { OWLObjectHasSelf, OWLObjectCardinalityRestriction, ClassExpressionType } = require('../../src/model/OWLClassExpression');
15
+ const { IRI } = require('../../src/model/IRI');
16
+
17
+ const EX = 'http://ex.org/';
18
+ const ont0 = () => new OWLOntology(new OWLOntologyID(IRI.create(EX)));
19
+
20
+ test('valid ontology has no violations', () => {
21
+ const ont = ont0();
22
+ ont.addAxiom(new OWLSubClassOfAxiom(new OWLClass(EX + 'A'), new OWLClass(EX + 'B')));
23
+ const v = new GlobalRestrictionsValidator().validate(ont);
24
+ assert.equal(v.length, 0);
25
+ });
26
+
27
+ test('functional property that is super of chain → violation', () => {
28
+ const ont = ont0();
29
+ const p = new OWLObjectProperty(EX + 'p');
30
+ const q = new OWLObjectProperty(EX + 'q');
31
+ const r = new OWLObjectProperty(EX + 'r');
32
+ ont.addAxiom(new OWLSubPropertyChainOfAxiom([q, r], p));
33
+ ont.addAxiom(new OWLFunctionalObjectPropertyAxiom(p));
34
+ const v = new GlobalRestrictionsValidator().validate(ont);
35
+ assert.ok(v.some(x => x.rule === 'simple-property'));
36
+ });
37
+
38
+ test('irreflexive property that is super of chain → violation', () => {
39
+ const ont = ont0();
40
+ const p = new OWLObjectProperty(EX + 'p');
41
+ const q = new OWLObjectProperty(EX + 'q');
42
+ const r = new OWLObjectProperty(EX + 'r');
43
+ ont.addAxiom(new OWLSubPropertyChainOfAxiom([q, r], p));
44
+ ont.addAxiom(new OWLIrreflexiveObjectPropertyAxiom(p));
45
+ const v = new GlobalRestrictionsValidator().validate(ont);
46
+ assert.ok(v.some(x => x.rule === 'simple-property'));
47
+ });
48
+
49
+ test('chain containing itself → regularity violation', () => {
50
+ const ont = ont0();
51
+ const p = new OWLObjectProperty(EX + 'p');
52
+ ont.addAxiom(new OWLSubPropertyChainOfAxiom([p, p], p));
53
+ const v = new GlobalRestrictionsValidator().validate(ont);
54
+ assert.ok(v.some(x => x.rule === 'regularity'));
55
+ });
56
+
57
+ test('instance of owl:Nothing → violation', () => {
58
+ const ont = ont0();
59
+ const i = new OWLNamedIndividual(EX + 'i');
60
+ const nothing = new OWLClass('http://www.w3.org/2002/07/owl#Nothing');
61
+ ont.addAxiom(new OWLClassAssertionAxiom(i, nothing));
62
+ const v = new GlobalRestrictionsValidator().validate(ont);
63
+ assert.ok(v.some(x => x.rule === 'owl:Nothing-instance'));
64
+ });
65
+
66
+ test('hasSelf on non-simple property → violation', () => {
67
+ const ont = ont0();
68
+ const p = new OWLObjectProperty(EX + 'p');
69
+ const q = new OWLObjectProperty(EX + 'q');
70
+ const r = new OWLObjectProperty(EX + 'r');
71
+ ont.addAxiom(new OWLSubPropertyChainOfAxiom([q, r], p));
72
+ ont.addAxiom(new OWLSubClassOfAxiom(
73
+ new OWLClass(EX + 'A'), new OWLObjectHasSelf(p)));
74
+ const v = new GlobalRestrictionsValidator().validate(ont);
75
+ assert.ok(v.some(x => x.rule === 'simple-property'));
76
+ });
@@ -0,0 +1,74 @@
1
+ 'use strict';
2
+
3
+ const test = require('node:test');
4
+ const assert = require('node:assert/strict');
5
+
6
+ const { ManchesterSyntaxParser } = require('../../src/io/ManchesterSyntaxParser');
7
+ const { FunctionalSyntaxParser } = require('../../src/io/FunctionalSyntaxParser');
8
+ const { SWRLBuiltins } = require('../../src/inference/SWRLReasoner');
9
+ const { SWRL_BUILTINS } = require('../../src/model/SWRL');
10
+
11
+ // --- L5 prefix fidelity ---
12
+
13
+ test('L5: Manchester parser records prefixes on ontology', () => {
14
+ const ont = new ManchesterSyntaxParser().parse(`
15
+ Prefix: ex: <http://ex.org/>
16
+ Class: ex:Widget
17
+ `);
18
+ assert.equal(ont.getPrefixes().ex, 'http://ex.org/');
19
+ });
20
+
21
+ test('L5: Functional syntax parser records prefixes on ontology', () => {
22
+ const ont = new FunctionalSyntaxParser().parse(`
23
+ Prefix(:=<http://ex.org/>)
24
+ Declaration(Class(<http://ex.org/Widget>))
25
+ `);
26
+ // default prefix key is ''
27
+ const pfx = ont.getPrefixes();
28
+ assert.ok(Object.values(pfx).includes('http://ex.org/'));
29
+ });
30
+
31
+ // --- L7 SWRL long-tail builtins ---
32
+
33
+ test('L7: stringEqualIgnoreCase', () => {
34
+ assert.equal(SWRLBuiltins.call('stringEqualIgnoreCase', ['Hello', 'hello']), true);
35
+ assert.equal(SWRLBuiltins.call('stringEqualIgnoreCase', ['Hello', 'world']), false);
36
+ });
37
+
38
+ test('L7: substringBefore / substringAfter', () => {
39
+ assert.equal(SWRLBuiltins.call('substringBefore', ['abc-def', '-']), 'abc');
40
+ assert.equal(SWRLBuiltins.call('substringAfter', ['abc-def', '-']), 'def');
41
+ });
42
+
43
+ test('L7: translate', () => {
44
+ assert.equal(SWRLBuiltins.call('translate', ['abc', 'abc', 'xyz']), 'xyz');
45
+ assert.equal(SWRLBuiltins.call('translate', ['aaa', 'a', 'b']), 'bbb');
46
+ });
47
+
48
+ test('L7: booleanNot', () => {
49
+ assert.equal(SWRLBuiltins.call('booleanNot', [true]), false);
50
+ assert.equal(SWRLBuiltins.call('booleanNot', [false]), true);
51
+ });
52
+
53
+ test('L7: list ops (member / length / first / rest / empty)', () => {
54
+ assert.equal(SWRLBuiltins.call('member', [2, [1, 2, 3]]), true);
55
+ assert.equal(SWRLBuiltins.call('length', [[1, 2, 3]]), 3);
56
+ assert.equal(SWRLBuiltins.call('first', [[7, 8, 9]]), 7);
57
+ assert.deepEqual(SWRLBuiltins.call('rest', [[7, 8, 9]]), [8, 9]);
58
+ assert.equal(SWRLBuiltins.call('empty', [[]]), true);
59
+ assert.equal(SWRLBuiltins.call('empty', [[1]]), false);
60
+ });
61
+
62
+ test('L7: sublist', () => {
63
+ assert.equal(SWRLBuiltins.call('sublist', [[1, 2, 3, 4], [2, 3]]), true);
64
+ assert.equal(SWRLBuiltins.call('sublist', [[1, 2, 3, 4], [3, 1]]), false);
65
+ });
66
+
67
+ test('L7: SWRL_BUILTINS registry includes long-tail names', () => {
68
+ const ns = 'http://www.w3.org/2003/11/swrlb#';
69
+ for (const b of ['stringEqualIgnoreCase', 'translate', 'substringBefore', 'substringAfter',
70
+ 'booleanNot', 'member', 'length', 'first', 'rest', 'sublist', 'empty',
71
+ 'listConcat', 'listIntersection', 'listSubtraction', 'anyURI', 'date', 'time']) {
72
+ assert.ok(SWRL_BUILTINS.includes(ns + b), 'missing builtin: ' + b);
73
+ }
74
+ });