@google-cloud/kcmd 0.0.0-stage → 0.2.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 (150) hide show
  1. package/LICENSE +203 -0
  2. package/README.md +264 -2
  3. package/build/ts/kcmd/cli.js +20252 -0
  4. package/build/ts/kcmd/gcp/alloydb.d.ts +12 -0
  5. package/build/ts/kcmd/gcp/alloydb.js +70 -0
  6. package/build/ts/kcmd/gcp/api.d.ts +29 -0
  7. package/build/ts/kcmd/gcp/api.js +162 -0
  8. package/build/ts/kcmd/gcp/biglake.d.ts +18 -0
  9. package/build/ts/kcmd/gcp/biglake.js +59 -0
  10. package/build/ts/kcmd/gcp/bigquery.d.ts +57 -0
  11. package/build/ts/kcmd/gcp/bigquery.js +134 -0
  12. package/build/ts/kcmd/gcp/context.d.ts +10 -0
  13. package/build/ts/kcmd/gcp/context.js +74 -0
  14. package/build/ts/kcmd/gcp/crm.d.ts +13 -0
  15. package/build/ts/kcmd/gcp/crm.js +91 -0
  16. package/build/ts/kcmd/gcp/dataplex.d.ts +147 -0
  17. package/build/ts/kcmd/gcp/dataplex.js +406 -0
  18. package/build/ts/kcmd/gcp/index.d.ts +3 -0
  19. package/build/ts/kcmd/gcp/index.js +21 -0
  20. package/build/ts/kcmd/gcp/spanner.d.ts +73 -0
  21. package/build/ts/kcmd/gcp/spanner.js +126 -0
  22. package/build/ts/kcmd/index.d.ts +7 -0
  23. package/build/ts/kcmd/index.js +46 -0
  24. package/build/ts/kcmd/layout.d.ts +16 -0
  25. package/build/ts/kcmd/layout.js +31 -0
  26. package/build/ts/kcmd/layouts/documents.d.ts +24 -0
  27. package/build/ts/kcmd/layouts/documents.js +264 -0
  28. package/build/ts/kcmd/layouts/okf.d.ts +31 -0
  29. package/build/ts/kcmd/layouts/okf.js +386 -0
  30. package/build/ts/kcmd/layouts/semantic-model.d.ts +74 -0
  31. package/build/ts/kcmd/layouts/semantic-model.js +621 -0
  32. package/build/ts/kcmd/layouts/standard.d.ts +13 -0
  33. package/build/ts/kcmd/layouts/standard.js +108 -0
  34. package/build/ts/kcmd/manifest.d.ts +34 -0
  35. package/build/ts/kcmd/manifest.js +262 -0
  36. package/build/ts/kcmd/metadata.d.ts +25 -0
  37. package/build/ts/kcmd/metadata.js +8 -0
  38. package/build/ts/kcmd/okf/catalog_residue.d.ts +14 -0
  39. package/build/ts/kcmd/okf/catalog_residue.js +124 -0
  40. package/build/ts/kcmd/okf/concept.d.ts +14 -0
  41. package/build/ts/kcmd/okf/concept.js +110 -0
  42. package/build/ts/kcmd/okf/concept_to_entry.d.ts +10 -0
  43. package/build/ts/kcmd/okf/concept_to_entry.js +281 -0
  44. package/build/ts/kcmd/okf/init_okf_workspace.d.ts +15 -0
  45. package/build/ts/kcmd/okf/init_okf_workspace.js +113 -0
  46. package/build/ts/kcmd/okf/links.d.ts +23 -0
  47. package/build/ts/kcmd/okf/links.js +468 -0
  48. package/build/ts/kcmd/okf/okf_metadata.d.ts +12 -0
  49. package/build/ts/kcmd/okf/okf_metadata.js +99 -0
  50. package/build/ts/kcmd/semantic/bigquery.d.ts +22 -0
  51. package/build/ts/kcmd/semantic/bigquery.js +469 -0
  52. package/build/ts/kcmd/semantic/binding.d.ts +3 -0
  53. package/build/ts/kcmd/semantic/binding.js +92 -0
  54. package/build/ts/kcmd/semantic/catalog_entry.d.ts +24 -0
  55. package/build/ts/kcmd/semantic/catalog_entry.js +35 -0
  56. package/build/ts/kcmd/semantic/converters/owl/convert.d.ts +26 -0
  57. package/build/ts/kcmd/semantic/converters/owl/convert.js +41 -0
  58. package/build/ts/kcmd/semantic/converters/owl/model.d.ts +98 -0
  59. package/build/ts/kcmd/semantic/converters/owl/model.js +30 -0
  60. package/build/ts/kcmd/semantic/converters/owl/parse.d.ts +11 -0
  61. package/build/ts/kcmd/semantic/converters/owl/parse.js +634 -0
  62. package/build/ts/kcmd/semantic/converters/owl/to_ir.d.ts +19 -0
  63. package/build/ts/kcmd/semantic/converters/owl/to_ir.js +390 -0
  64. package/build/ts/kcmd/semantic/deploy_bigquery.d.ts +20 -0
  65. package/build/ts/kcmd/semantic/deploy_bigquery.js +226 -0
  66. package/build/ts/kcmd/semantic/deploy_knowledge_catalog.d.ts +104 -0
  67. package/build/ts/kcmd/semantic/deploy_knowledge_catalog.js +1367 -0
  68. package/build/ts/kcmd/semantic/deploy_spanner.d.ts +15 -0
  69. package/build/ts/kcmd/semantic/deploy_spanner.js +150 -0
  70. package/build/ts/kcmd/semantic/deployment_target.d.ts +93 -0
  71. package/build/ts/kcmd/semantic/deployment_target.js +379 -0
  72. package/build/ts/kcmd/semantic/graph_ddl.d.ts +44 -0
  73. package/build/ts/kcmd/semantic/graph_ddl.js +656 -0
  74. package/build/ts/kcmd/semantic/import_model.d.ts +72 -0
  75. package/build/ts/kcmd/semantic/import_model.js +1698 -0
  76. package/build/ts/kcmd/semantic/ir.d.ts +589 -0
  77. package/build/ts/kcmd/semantic/ir.js +247 -0
  78. package/build/ts/kcmd/semantic/kc_actions.d.ts +45 -0
  79. package/build/ts/kcmd/semantic/kc_actions.js +531 -0
  80. package/build/ts/kcmd/semantic/kc_constraints.d.ts +44 -0
  81. package/build/ts/kcmd/semantic/kc_constraints.js +279 -0
  82. package/build/ts/kcmd/semantic/kc_converter.d.ts +37 -0
  83. package/build/ts/kcmd/semantic/kc_converter.js +839 -0
  84. package/build/ts/kcmd/semantic/kc_custom_types.d.ts +63 -0
  85. package/build/ts/kcmd/semantic/kc_custom_types.js +751 -0
  86. package/build/ts/kcmd/semantic/kc_entries.d.ts +155 -0
  87. package/build/ts/kcmd/semantic/kc_entries.js +284 -0
  88. package/build/ts/kcmd/semantic/kc_ids.d.ts +102 -0
  89. package/build/ts/kcmd/semantic/kc_ids.js +188 -0
  90. package/build/ts/kcmd/semantic/knowledge_catalog.d.ts +29 -0
  91. package/build/ts/kcmd/semantic/knowledge_catalog.js +960 -0
  92. package/build/ts/kcmd/semantic/loader.d.ts +258 -0
  93. package/build/ts/kcmd/semantic/loader.js +3576 -0
  94. package/build/ts/kcmd/semantic/names.d.ts +10 -0
  95. package/build/ts/kcmd/semantic/names.js +85 -0
  96. package/build/ts/kcmd/semantic/osi_converter.d.ts +60 -0
  97. package/build/ts/kcmd/semantic/osi_converter.js +910 -0
  98. package/build/ts/kcmd/semantic/parameters.d.ts +19 -0
  99. package/build/ts/kcmd/semantic/parameters.js +171 -0
  100. package/build/ts/kcmd/semantic/pull_kc.d.ts +10 -0
  101. package/build/ts/kcmd/semantic/pull_kc.js +272 -0
  102. package/build/ts/kcmd/semantic/resolve_inheritance.d.ts +59 -0
  103. package/build/ts/kcmd/semantic/resolve_inheritance.js +346 -0
  104. package/build/ts/kcmd/semantic/resolve_profiles.d.ts +291 -0
  105. package/build/ts/kcmd/semantic/resolve_profiles.js +2003 -0
  106. package/build/ts/kcmd/semantic/runtime/agent_tools.d.ts +93 -0
  107. package/build/ts/kcmd/semantic/runtime/agent_tools.js +243 -0
  108. package/build/ts/kcmd/semantic/runtime/dialect.d.ts +13 -0
  109. package/build/ts/kcmd/semantic/runtime/dialect.js +39 -0
  110. package/build/ts/kcmd/semantic/runtime/runtime.d.ts +88 -0
  111. package/build/ts/kcmd/semantic/runtime/runtime.js +301 -0
  112. package/build/ts/kcmd/semantic/runtime/store.d.ts +112 -0
  113. package/build/ts/kcmd/semantic/runtime/store.js +344 -0
  114. package/build/ts/kcmd/semantic/skills.d.ts +110 -0
  115. package/build/ts/kcmd/semantic/skills.js +697 -0
  116. package/build/ts/kcmd/semantic/source_dialect.d.ts +17 -0
  117. package/build/ts/kcmd/semantic/source_dialect.js +311 -0
  118. package/build/ts/kcmd/semantic/source_entries.d.ts +12 -0
  119. package/build/ts/kcmd/semantic/source_entries.js +341 -0
  120. package/build/ts/kcmd/semantic/spanner.d.ts +18 -0
  121. package/build/ts/kcmd/semantic/spanner.js +60 -0
  122. package/build/ts/kcmd/semantic/sql_expr_utils.d.ts +23 -0
  123. package/build/ts/kcmd/semantic/sql_expr_utils.js +394 -0
  124. package/build/ts/kcmd/semantic/sql_identifiers.d.ts +6 -0
  125. package/build/ts/kcmd/semantic/sql_identifiers.js +267 -0
  126. package/build/ts/kcmd/semantic/sql_parser.d.ts +47 -0
  127. package/build/ts/kcmd/semantic/sql_parser.js +400 -0
  128. package/build/ts/kcmd/semantic/transpile.d.ts +76 -0
  129. package/build/ts/kcmd/semantic/transpile.js +581 -0
  130. package/build/ts/kcmd/semantic/validate.d.ts +70 -0
  131. package/build/ts/kcmd/semantic/validate.js +2266 -0
  132. package/build/ts/kcmd/semantic/yaml_options.d.ts +6 -0
  133. package/build/ts/kcmd/semantic/yaml_options.js +58 -0
  134. package/build/ts/kcmd/semantic/yaml_update.d.ts +26 -0
  135. package/build/ts/kcmd/semantic/yaml_update.js +782 -0
  136. package/build/ts/kcmd/snapshot.d.ts +37 -0
  137. package/build/ts/kcmd/snapshot.js +386 -0
  138. package/build/ts/kcmd/source.d.ts +31 -0
  139. package/build/ts/kcmd/source.js +119 -0
  140. package/build/ts/kcmd/sources/bq-dataset.d.ts +17 -0
  141. package/build/ts/kcmd/sources/bq-dataset.js +131 -0
  142. package/build/ts/kcmd/sources/entrygroup.d.ts +21 -0
  143. package/build/ts/kcmd/sources/entrygroup.js +83 -0
  144. package/build/ts/kcmd/sources/kb.d.ts +21 -0
  145. package/build/ts/kcmd/sources/kb.js +82 -0
  146. package/build/ts/kcmd/sources/semantic-model.d.ts +18 -0
  147. package/build/ts/kcmd/sources/semantic-model.js +48 -0
  148. package/build/ts/kcmd/sync.d.ts +35 -0
  149. package/build/ts/kcmd/sync.js +734 -0
  150. package/package.json +62 -4
@@ -0,0 +1,634 @@
1
+ "use strict";
2
+ // Turtle (.ttl) -> OwlModel parser.
3
+ //
4
+ // A mechanical triples-to-structs step: it reads RDF with `n3`, recognizes the
5
+ // OWL/RDFS/SKOS/Dublin-Core terms the converter supports, and fills the staging
6
+ // OwlModel (model.ts). All OWL -> OSI mapping policy lives in to_ir.ts, not
7
+ // here; this file only decides "which triples matter and where do their values
8
+ // go".
9
+ //
10
+ // Declaration order is preserved: classes and properties appear in the order
11
+ // their `rdf:type` triple is first seen in the document, so the generated OSI
12
+ // is stable across runs (and matches its golden).
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.localName = localName;
15
+ exports.namespace = namespace;
16
+ exports.parseOwl = parseOwl;
17
+ const n3_1 = require("n3");
18
+ // RDF/RDFS/OWL/SKOS/Dublin-Core term IRIs we recognize. Only these; anything
19
+ // else is carried by neither the parser nor the model (see the user guide's
20
+ // "not covered yet").
21
+ const RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#';
22
+ const RDFS = 'http://www.w3.org/2000/01/rdf-schema#';
23
+ const OWL = 'http://www.w3.org/2002/07/owl#';
24
+ const SKOS = 'http://www.w3.org/2004/02/skos/core#';
25
+ const DCTERMS = 'http://purl.org/dc/terms/';
26
+ const DC = 'http://purl.org/dc/elements/1.1/';
27
+ const XSD = 'http://www.w3.org/2001/XMLSchema#';
28
+ const XSD_BOOLEAN = `${XSD}boolean`;
29
+ const XSD_STRING = `${XSD}string`;
30
+ // The two lexical forms of xsd:boolean `true` (XSD admits both `true` and `1`);
31
+ // `false`/`0` restate the default and are not carried (see the OWL_DEPRECATED
32
+ // case).
33
+ const XSD_BOOLEAN_TRUE = new Set(['true', '1']);
34
+ const RDF_TYPE = `${RDF}type`;
35
+ // RDF collection (list) terms, used to walk an owl:hasKey list.
36
+ const RDF_FIRST = `${RDF}first`;
37
+ const RDF_REST = `${RDF}rest`;
38
+ const RDF_NIL = `${RDF}nil`;
39
+ const OWL_CLASS = `${OWL}Class`;
40
+ const OWL_DATATYPE_PROPERTY = `${OWL}DatatypeProperty`;
41
+ const OWL_OBJECT_PROPERTY = `${OWL}ObjectProperty`;
42
+ const OWL_INVERSE_FUNCTIONAL_PROPERTY = `${OWL}InverseFunctionalProperty`;
43
+ // Property characteristics carried verbatim (no native OSI home). Recognized by
44
+ // their rdf:type, like owl:InverseFunctionalProperty, and collected as
45
+ // typed-subject sets.
46
+ const OWL_SYMMETRIC_PROPERTY = `${OWL}SymmetricProperty`;
47
+ const OWL_TRANSITIVE_PROPERTY = `${OWL}TransitiveProperty`;
48
+ const OWL_FUNCTIONAL_PROPERTY = `${OWL}FunctionalProperty`;
49
+ const OWL_REFLEXIVE_PROPERTY = `${OWL}ReflexiveProperty`;
50
+ const OWL_IRREFLEXIVE_PROPERTY = `${OWL}IrreflexiveProperty`;
51
+ const OWL_ASYMMETRIC_PROPERTY = `${OWL}AsymmetricProperty`;
52
+ const OWL_ONTOLOGY = `${OWL}Ontology`;
53
+ const OWL_HAS_KEY = `${OWL}hasKey`;
54
+ // List-valued constructs whose object is an RDF collection head (a blank node),
55
+ // resolved with the same list walker as owl:hasKey. owl:oneOf enumerates a
56
+ // class's members; owl:propertyChainAxiom composes a property from a sequence
57
+ // of others. Both are carried verbatim (no native OSI home).
58
+ const OWL_ONE_OF = `${OWL}oneOf`;
59
+ const OWL_PROPERTY_CHAIN_AXIOM = `${OWL}propertyChainAxiom`;
60
+ const OWL_INVERSE_OF = `${OWL}inverseOf`;
61
+ const OWL_EQUIVALENT_PROPERTY = `${OWL}equivalentProperty`;
62
+ const OWL_PROPERTY_DISJOINT_WITH = `${OWL}propertyDisjointWith`;
63
+ const OWL_DISJOINT_WITH = `${OWL}disjointWith`;
64
+ const OWL_DEPRECATED = `${OWL}deprecated`;
65
+ const OWL_VERSION_INFO = `${OWL}versionInfo`;
66
+ const OWL_THING = `${OWL}Thing`;
67
+ // Set-level axioms. Each is asserted on an ANONYMOUS node (not a named term)
68
+ // typed with one of these, whose `owl:members` list names the set the axiom
69
+ // constrains. owl:AllDifferent also accepts the legacy OWL 1
70
+ // `owl:distinctMembers` spelling. Carried verbatim at the model level (no
71
+ // native OSI home).
72
+ const OWL_ALL_DISJOINT_CLASSES = `${OWL}AllDisjointClasses`;
73
+ const OWL_ALL_DISJOINT_PROPERTIES = `${OWL}AllDisjointProperties`;
74
+ const OWL_ALL_DIFFERENT = `${OWL}AllDifferent`;
75
+ const OWL_MEMBERS = `${OWL}members`;
76
+ const OWL_DISTINCT_MEMBERS = `${OWL}distinctMembers`;
77
+ const RDFS_LABEL = `${RDFS}label`;
78
+ const RDFS_COMMENT = `${RDFS}comment`;
79
+ const RDFS_DOMAIN = `${RDFS}domain`;
80
+ const RDFS_RANGE = `${RDFS}range`;
81
+ const RDFS_SUBCLASS_OF = `${RDFS}subClassOf`;
82
+ const RDFS_SUBPROPERTY_OF = `${RDFS}subPropertyOf`;
83
+ const RDFS_SEE_ALSO = `${RDFS}seeAlso`;
84
+ const RDFS_IS_DEFINED_BY = `${RDFS}isDefinedBy`;
85
+ const OWL_EQUIVALENT_CLASS = `${OWL}equivalentClass`;
86
+ const RDFS_RESOURCE = `${RDFS}Resource`;
87
+ // The implicit universal superclasses: every class is trivially a subclass of
88
+ // owl:Thing / rdfs:Resource, so an explicit `rdfs:subClassOf` naming one
89
+ // carries no inheritance information and is not recorded as `extends` (nor
90
+ // warned about).
91
+ const TOP_CLASS_IRIS = new Set([OWL_THING, RDFS_RESOURCE]);
92
+ const SKOS_ALT_LABEL = `${SKOS}altLabel`;
93
+ const SKOS_PREF_LABEL = `${SKOS}prefLabel`;
94
+ const SKOS_HIDDEN_LABEL = `${SKOS}hiddenLabel`;
95
+ const SKOS_DEFINITION = `${SKOS}definition`;
96
+ const SKOS_EXAMPLE = `${SKOS}example`;
97
+ const DCTERMS_DESCRIPTION = `${DCTERMS}description`;
98
+ const DC_DESCRIPTION = `${DC}description`;
99
+ const KIND_BY_TYPE = {
100
+ [OWL_CLASS]: 'class',
101
+ [OWL_DATATYPE_PROPERTY]: 'datatypeProperty',
102
+ [OWL_OBJECT_PROPERTY]: 'objectProperty',
103
+ };
104
+ // The namespace-stripped local name of a term IRI: the part after the last `#`
105
+ // or `/`. This is the OSI-facing identity of an in-namespace term (e.g. an
106
+ // entity/field name); the mapper also uses it to shorten a carried in-namespace
107
+ // cross-reference (see to_ir.refValue). Exported for that mapper use.
108
+ function localName(iri) {
109
+ const cut = Math.max(iri.lastIndexOf('#'), iri.lastIndexOf('/'));
110
+ return cut >= 0 ? iri.slice(cut + 1) : iri;
111
+ }
112
+ // The namespace portion of a term IRI (everything up to and including the last
113
+ // `#`/`/`); the ontology's base IRI for provenance, and the key the mapper
114
+ // compares against to decide whether a cross-reference is in-namespace (see
115
+ // to_ir.refValue). Exported for that mapper use.
116
+ function namespace(iri) {
117
+ const cut = Math.max(iri.lastIndexOf('#'), iri.lastIndexOf('/'));
118
+ return cut >= 0 ? iri.slice(0, cut + 1) : undefined;
119
+ }
120
+ // Renders a literal term in the N-Triples form used to carry an rdfs:seeAlso
121
+ // literal (see the RDFS_SEE_ALSO case): the lexical value wrapped in double
122
+ // quotes, followed by an optional `@lang` language tag or `^^<datatype>` type
123
+ // IRI so a language-tagged or typed literal round-trips rather than collapsing
124
+ // to a bare string. A plain xsd:string carries no suffix (it is the implicit
125
+ // default). Backslash and double quote in the value are escaped, the two
126
+ // characters that would otherwise break the wrapping. Reversed by parsing the
127
+ // N-Triples literal grammar.
128
+ function ntriplesLiteral(value, language, datatype) {
129
+ const quoted = `"${value.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
130
+ if (language)
131
+ return `${quoted}@${language}`;
132
+ if (datatype && datatype !== XSD_STRING)
133
+ return `${quoted}^^<${datatype}>`;
134
+ return quoted;
135
+ }
136
+ // The most common namespace among a set of term IRIs -- the ontology's own
137
+ // namespace. A tie (or a single term) resolves to the first in document order,
138
+ // since `best` is only replaced on a STRICTLY greater count. Returns undefined
139
+ // for an empty set (a document with no typed terms). Delimiter-exact, unlike
140
+ // deriving the base from the ontology IRI (which often omits the trailing
141
+ // `#`/`/`).
142
+ function dominantNamespace(iris) {
143
+ const counts = new Map();
144
+ let best;
145
+ let bestCount = 0;
146
+ for (const iri of iris) {
147
+ const ns = namespace(iri);
148
+ if (ns === undefined)
149
+ continue;
150
+ const n = (counts.get(ns) ?? 0) + 1;
151
+ counts.set(ns, n);
152
+ if (n > bestCount) {
153
+ bestCount = n;
154
+ best = ns;
155
+ }
156
+ }
157
+ return best;
158
+ }
159
+ function emptyAnnotations() {
160
+ return {
161
+ synonyms: [],
162
+ examples: [],
163
+ domains: [],
164
+ ranges: [],
165
+ keyListHeads: [],
166
+ oneOfListHeads: [],
167
+ chainListHeads: [],
168
+ subClassOf: [],
169
+ subPropertyOf: [],
170
+ equivalentClass: [],
171
+ inverseOf: [],
172
+ disjointWith: [],
173
+ equivalentProperty: [],
174
+ propertyDisjointWith: [],
175
+ seeAlso: [],
176
+ isDefinedBy: [],
177
+ deprecated: false
178
+ };
179
+ }
180
+ // The effective description: the first present of rdfs:comment,
181
+ // skos:definition, dcterms:description, dc:description -- a fixed precedence so
182
+ // a term with more than one carries the most specific.
183
+ function descriptionOf(a) {
184
+ return a.rdfsComment ?? a.skosDefinition ?? a.dctermsDescription ??
185
+ a.dcDescription;
186
+ }
187
+ // The per-term carried annotations (rdfs:seeAlso / isDefinedBy, owl:deprecated
188
+ // / versionInfo), shared by classes and both property kinds, projected from the
189
+ // accumulator into the model's common-annotation shape.
190
+ function commonAnnotations(a) {
191
+ return {
192
+ seeAlso: a.seeAlso,
193
+ isDefinedBy: a.isDefinedBy,
194
+ deprecated: a.deprecated,
195
+ versionInfo: a.versionInfo,
196
+ };
197
+ }
198
+ /**
199
+ * Parses a Turtle document into an OwlModel.
200
+ *
201
+ * Synchronous: `n3`'s Parser returns the full quad array when called without a
202
+ * callback, which suits a one-shot file import. Throws on malformed Turtle (the
203
+ * parser's own error), which the CLI surfaces.
204
+ */
205
+ function parseOwl(turtle) {
206
+ const quads = new n3_1.Parser().parse(turtle);
207
+ // Pass 1: types. An ordered list of typed subjects (first `rdf:type`
208
+ // occurrence wins the position) plus a kind index; the set of
209
+ // inverse-functional subjects and the ontology-header subject, which are
210
+ // recognized by their type but are not themselves classes/properties.
211
+ // Scanning `quads` directly (not the Store) keeps document order.
212
+ const order = [];
213
+ const kind = new Map();
214
+ const inverseFunctional = new Set();
215
+ // Property characteristics carried verbatim, each a set of the subjects typed
216
+ // with it. A property is commonly typed with several types (e.g.
217
+ // `a owl:ObjectProperty, owl:SymmetricProperty`), so a characteristic type is
218
+ // recorded here and does not compete with the kind that routes it to a
219
+ // class/property.
220
+ const symmetric = new Set();
221
+ const transitive = new Set();
222
+ const functional = new Set();
223
+ const reflexive = new Set();
224
+ const irreflexive = new Set();
225
+ const asymmetric = new Set();
226
+ // Anonymous set-level-axiom nodes, in document order, deduped by node id
227
+ // within each kind (a duplicate type triple must not list the node twice). A
228
+ // node typed as two different kinds -- legal, if unusual, RDF -- is recorded
229
+ // under each, so the dedup is per-kind rather than one shared seen-set. Their
230
+ // `owl:members` list is resolved after the list structure is known.
231
+ const allDisjointClassesNodes = [];
232
+ const allDisjointPropertiesNodes = [];
233
+ const allDifferentNodes = [];
234
+ const seenDisjointClasses = new Set();
235
+ const seenDisjointProperties = new Set();
236
+ const seenDifferent = new Set();
237
+ let ontologyIri;
238
+ for (const q of quads) {
239
+ if (q.predicate.value !== RDF_TYPE)
240
+ continue;
241
+ const type = q.object.value;
242
+ const subject = q.subject.value;
243
+ if (type === OWL_INVERSE_FUNCTIONAL_PROPERTY) {
244
+ inverseFunctional.add(subject);
245
+ continue;
246
+ }
247
+ if (type === OWL_SYMMETRIC_PROPERTY) {
248
+ symmetric.add(subject);
249
+ continue;
250
+ }
251
+ if (type === OWL_TRANSITIVE_PROPERTY) {
252
+ transitive.add(subject);
253
+ continue;
254
+ }
255
+ if (type === OWL_FUNCTIONAL_PROPERTY) {
256
+ functional.add(subject);
257
+ continue;
258
+ }
259
+ if (type === OWL_REFLEXIVE_PROPERTY) {
260
+ reflexive.add(subject);
261
+ continue;
262
+ }
263
+ if (type === OWL_IRREFLEXIVE_PROPERTY) {
264
+ irreflexive.add(subject);
265
+ continue;
266
+ }
267
+ if (type === OWL_ASYMMETRIC_PROPERTY) {
268
+ asymmetric.add(subject);
269
+ continue;
270
+ }
271
+ if (type === OWL_ONTOLOGY) {
272
+ if (ontologyIri === undefined)
273
+ ontologyIri = subject;
274
+ continue;
275
+ }
276
+ if (type === OWL_ALL_DISJOINT_CLASSES) {
277
+ if (!seenDisjointClasses.has(subject)) {
278
+ seenDisjointClasses.add(subject);
279
+ allDisjointClassesNodes.push(subject);
280
+ }
281
+ continue;
282
+ }
283
+ if (type === OWL_ALL_DISJOINT_PROPERTIES) {
284
+ if (!seenDisjointProperties.has(subject)) {
285
+ seenDisjointProperties.add(subject);
286
+ allDisjointPropertiesNodes.push(subject);
287
+ }
288
+ continue;
289
+ }
290
+ if (type === OWL_ALL_DIFFERENT) {
291
+ if (!seenDifferent.has(subject)) {
292
+ seenDifferent.add(subject);
293
+ allDifferentNodes.push(subject);
294
+ }
295
+ continue;
296
+ }
297
+ const k = KIND_BY_TYPE[type];
298
+ if (!k)
299
+ continue;
300
+ if (!kind.has(subject)) {
301
+ kind.set(subject, k);
302
+ order.push(subject);
303
+ }
304
+ }
305
+ // Pass 2: RDF list structure (rdf:first / rdf:rest), so an owl:hasKey list
306
+ // can be resolved to its member properties. List nodes are blank nodes
307
+ // unrelated to the typed subjects, so they are collected separately.
308
+ const listFirst = new Map();
309
+ const listRest = new Map();
310
+ // The `owl:members` list head of each set-level-axiom node. owl:members (OWL
311
+ // 2) wins over the legacy owl:distinctMembers (OWL 1, owl:AllDifferent only)
312
+ // when a node carries both, regardless of the order the two triples appear.
313
+ // owl:distinctMembers is honored ONLY on an owl:AllDifferent node, matching
314
+ // the OWL spec (it has no meaning on the disjointness axioms), so a stray
315
+ // owl:distinctMembers on an owl:AllDisjoint* node is ignored rather than
316
+ // carried.
317
+ const membersHead = new Map();
318
+ for (const q of quads) {
319
+ if (q.predicate.value === RDF_FIRST)
320
+ listFirst.set(q.subject.value, q.object.value);
321
+ else if (q.predicate.value === RDF_REST)
322
+ listRest.set(q.subject.value, q.object.value);
323
+ else if (q.predicate.value === OWL_MEMBERS)
324
+ membersHead.set(q.subject.value, q.object.value);
325
+ else if (q.predicate.value === OWL_DISTINCT_MEMBERS &&
326
+ seenDifferent.has(q.subject.value) && !membersHead.has(q.subject.value))
327
+ membersHead.set(q.subject.value, q.object.value);
328
+ }
329
+ // Resolves an RDF collection to its member IRIs, following rdf:rest to nil.
330
+ // Defensive against a cycle or a missing link (stops at the first gap).
331
+ const resolveList = (head) => {
332
+ const out = [];
333
+ const seen = new Set();
334
+ let node = head;
335
+ while (node && node !== RDF_NIL && !seen.has(node)) {
336
+ seen.add(node);
337
+ const value = listFirst.get(node);
338
+ if (value === undefined)
339
+ break;
340
+ out.push(value);
341
+ node = listRest.get(node);
342
+ }
343
+ return out;
344
+ };
345
+ // Pass 3: accumulate annotations for each typed subject (and the ontology
346
+ // header) in document order, so the first label is the primary and the rest
347
+ // are synonyms.
348
+ const annotations = new Map();
349
+ const annotationsFor = (iri) => {
350
+ let a = annotations.get(iri);
351
+ if (!a) {
352
+ a = emptyAnnotations();
353
+ annotations.set(iri, a);
354
+ }
355
+ return a;
356
+ };
357
+ const annotated = (iri) => kind.has(iri) || iri === ontologyIri;
358
+ for (const q of quads) {
359
+ const subject = q.subject.value;
360
+ if (!annotated(subject))
361
+ continue;
362
+ const a = annotationsFor(subject);
363
+ switch (q.predicate.value) {
364
+ case RDFS_LABEL:
365
+ // First label -> the display label; any further label -> a synonym.
366
+ if (a.label === undefined)
367
+ a.label = q.object.value;
368
+ else
369
+ a.synonyms.push(q.object.value);
370
+ break;
371
+ case SKOS_ALT_LABEL:
372
+ case SKOS_PREF_LABEL:
373
+ case SKOS_HIDDEN_LABEL:
374
+ a.synonyms.push(q.object.value);
375
+ break;
376
+ case SKOS_EXAMPLE:
377
+ a.examples.push(q.object.value);
378
+ break;
379
+ case RDFS_COMMENT:
380
+ a.rdfsComment = q.object.value;
381
+ break;
382
+ case SKOS_DEFINITION:
383
+ a.skosDefinition = q.object.value;
384
+ break;
385
+ case DCTERMS_DESCRIPTION:
386
+ a.dctermsDescription = q.object.value;
387
+ break;
388
+ case DC_DESCRIPTION:
389
+ a.dcDescription = q.object.value;
390
+ break;
391
+ case RDFS_DOMAIN:
392
+ a.domains.push(localName(q.object.value));
393
+ break;
394
+ case RDFS_RANGE:
395
+ a.ranges.push(q.object.value); // kept as IRI; mapper maps xsd:*
396
+ break;
397
+ case OWL_VERSION_INFO:
398
+ a.versionInfo = q.object.value;
399
+ break;
400
+ case OWL_HAS_KEY:
401
+ a.keyListHeads.push(q.object.value);
402
+ break;
403
+ case OWL_ONE_OF:
404
+ // Enumerated class -> no native OSI home; carried verbatim. The object
405
+ // is an RDF collection head; the members (usually individuals) are
406
+ // resolved with the list walker at build time. This is recorded for any
407
+ // annotated subject, but only the class build reads it -- if the
408
+ // subject is typed a property instead, the heads are collected here and
409
+ // then dropped (an owl:oneOf on a property is not meaningful).
410
+ a.oneOfListHeads.push(q.object.value);
411
+ break;
412
+ case OWL_PROPERTY_CHAIN_AXIOM:
413
+ // Property chain -> no native OSI home; carried verbatim. The object is
414
+ // an RDF collection head naming the composed properties, in order.
415
+ a.chainListHeads.push(q.object.value);
416
+ break;
417
+ case RDFS_SUBCLASS_OF:
418
+ // Class hierarchy -> the entity's `extends`. Named superclasses only:
419
+ // a blank-node object (an owl:Restriction and similar axioms) is not a
420
+ // named class, so it is ignored here (out of scope). The implicit
421
+ // universal superclasses (owl:Thing / rdfs:Resource) are ignored too --
422
+ // every class subclasses them, so they carry no inheritance
423
+ // information.
424
+ if (q.object.termType === 'NamedNode' &&
425
+ !TOP_CLASS_IRIS.has(q.object.value))
426
+ a.subClassOf.push(localName(q.object.value));
427
+ break;
428
+ case RDFS_SUBPROPERTY_OF:
429
+ // Property hierarchy -> no native OSI home; carried verbatim by the
430
+ // mapper as a custom extension. Named superproperties only (a
431
+ // blank-node property expression is out of scope). The full IRI is
432
+ // kept; the mapper shortens an in-namespace one (see to_ir.refValue).
433
+ if (q.object.termType === 'NamedNode')
434
+ a.subPropertyOf.push(q.object.value);
435
+ break;
436
+ case OWL_EQUIVALENT_CLASS:
437
+ // Class equivalence -> no native OSI home; carried verbatim. Named
438
+ // classes only; a blank-node class expression (owl:intersectionOf, ...)
439
+ // is a class definition, not a plain cross-reference, so it is ignored
440
+ // (out of scope, like a blank-node subClassOf).
441
+ if (q.object.termType === 'NamedNode')
442
+ a.equivalentClass.push(q.object.value);
443
+ break;
444
+ case OWL_DISJOINT_WITH:
445
+ // Class disjointness -> no native OSI home; carried verbatim. Named
446
+ // classes only (a blank-node class expression is out of scope).
447
+ if (q.object.termType === 'NamedNode')
448
+ a.disjointWith.push(q.object.value);
449
+ break;
450
+ case OWL_INVERSE_OF:
451
+ // Inverse edge -> no native OSI home; carried verbatim. Named object
452
+ // properties only.
453
+ if (q.object.termType === 'NamedNode')
454
+ a.inverseOf.push(q.object.value);
455
+ break;
456
+ case OWL_EQUIVALENT_PROPERTY:
457
+ // Property equivalence -> no native OSI home; carried verbatim. Named
458
+ // properties only.
459
+ if (q.object.termType === 'NamedNode')
460
+ a.equivalentProperty.push(q.object.value);
461
+ break;
462
+ case OWL_PROPERTY_DISJOINT_WITH:
463
+ // Property disjointness -> no native OSI home; carried verbatim. Named
464
+ // properties only.
465
+ if (q.object.termType === 'NamedNode')
466
+ a.propertyDisjointWith.push(q.object.value);
467
+ break;
468
+ case RDFS_SEE_ALSO:
469
+ // A pointer to further information -> carried verbatim as an N-Triples
470
+ // object term, so an IRI stays distinguishable from a literal on
471
+ // round-trip: an IRI as `<iri>`, a literal as `"text"` with any
472
+ // language tag (`@en`) or datatype (`^^<iri>`) preserved (see
473
+ // ntriplesLiteral). seeAlso is the only carried slot that admits either
474
+ // kind; every other carries a bare IRI or local name. A blank node has
475
+ // no stable identity to carry, so it is skipped.
476
+ if (q.object.termType === 'NamedNode')
477
+ a.seeAlso.push(`<${q.object.value}>`);
478
+ else if (q.object.termType === 'Literal')
479
+ a.seeAlso.push(ntriplesLiteral(q.object.value, q.object.language, q.object.datatype?.value ?? ''));
480
+ break;
481
+ case RDFS_IS_DEFINED_BY:
482
+ // The resource (usually the defining ontology) that defines this term
483
+ // -> carried verbatim. Named resources only.
484
+ if (q.object.termType === 'NamedNode')
485
+ a.isDefinedBy.push(q.object.value);
486
+ break;
487
+ case OWL_DEPRECATED:
488
+ // Lifecycle flag -> carried only for an xsd:boolean literal that is
489
+ // `true`. That is the one meaningful assertion; an explicit `false`/`0`
490
+ // restates the default, and a non-boolean value (e.g. the string
491
+ // "true") is malformed -- neither is carried. Both XSD lexical forms of
492
+ // true (`true` and `1`) are accepted.
493
+ if (q.object.termType === 'Literal' &&
494
+ q.object.datatype?.value === XSD_BOOLEAN &&
495
+ XSD_BOOLEAN_TRUE.has(q.object.value))
496
+ a.deprecated = true;
497
+ break;
498
+ default:
499
+ break;
500
+ }
501
+ }
502
+ const classes = [];
503
+ const datatypeProperties = [];
504
+ const objectProperties = [];
505
+ // The ontology's own namespace: the one shared by MOST of its typed terms.
506
+ // Taking the most common namespace (not merely the first typed term's) is
507
+ // robust to a document that also types a handful of foreign-namespace terms
508
+ // -- e.g. an imported class it annotates -- which would otherwise hijack the
509
+ // base if one happened to appear first and silently invert the mapper's
510
+ // in-namespace/cross-namespace shortening (see to_ir.refValue).
511
+ let baseIri = dominantNamespace(order);
512
+ for (const iri of order) {
513
+ const a = annotations.get(iri) ?? emptyAnnotations();
514
+ switch (kind.get(iri)) {
515
+ case 'class':
516
+ classes.push({
517
+ localName: localName(iri),
518
+ label: a.label,
519
+ comment: descriptionOf(a),
520
+ synonyms: a.synonyms,
521
+ examples: a.examples,
522
+ keys: a.keyListHeads.flatMap(resolveList).map(localName),
523
+ subClassOf: a.subClassOf,
524
+ equivalentClass: a.equivalentClass,
525
+ disjointWith: a.disjointWith,
526
+ // Full member IRIs of the enumeration set (a carried cross-reference;
527
+ // the mapper shortens an in-namespace one). flatMap unions the
528
+ // members across every oneOf head -- an enumeration is a set, so the
529
+ // mapper dedupes and order does not matter (contrast propertyChain).
530
+ oneOf: a.oneOfListHeads.flatMap(resolveList),
531
+ ...commonAnnotations(a),
532
+ });
533
+ break;
534
+ case 'datatypeProperty':
535
+ datatypeProperties.push({
536
+ localName: localName(iri),
537
+ domains: a.domains,
538
+ rangeIri: a.ranges[0],
539
+ label: a.label,
540
+ comment: descriptionOf(a),
541
+ synonyms: a.synonyms,
542
+ examples: a.examples,
543
+ inverseFunctional: inverseFunctional.has(iri),
544
+ functional: functional.has(iri),
545
+ subPropertyOf: a.subPropertyOf,
546
+ equivalentProperty: a.equivalentProperty,
547
+ propertyDisjointWith: a.propertyDisjointWith,
548
+ ...commonAnnotations(a),
549
+ });
550
+ break;
551
+ case 'objectProperty':
552
+ objectProperties.push({
553
+ localName: localName(iri),
554
+ // a.domains are already local names; a.ranges are raw IRIs. Carry all
555
+ // of each so the mapper can warn about (and drop) the extras rather
556
+ // than silently keeping only the first.
557
+ domains: a.domains,
558
+ ranges: a.ranges.map(localName),
559
+ label: a.label,
560
+ comment: descriptionOf(a),
561
+ synonyms: a.synonyms,
562
+ examples: a.examples,
563
+ subPropertyOf: a.subPropertyOf,
564
+ inverseOf: a.inverseOf,
565
+ equivalentProperty: a.equivalentProperty,
566
+ propertyDisjointWith: a.propertyDisjointWith,
567
+ // One resolved chain per owl:propertyChainAxiom (map, NOT flatMap):
568
+ // OWL 2 permits several chain axioms on one property, and fusing them
569
+ // would be indistinguishable from a single longer chain. Full
570
+ // property IRIs in chain order (the mapper shortens in-namespace
571
+ // ones); within a chain order and repetition are preserved, so no
572
+ // dedupe. An empty chain (a broken/gapped list) is dropped rather
573
+ // than carried as [].
574
+ propertyChain: a.chainListHeads.map(resolveList).filter(c => c.length),
575
+ symmetric: symmetric.has(iri),
576
+ transitive: transitive.has(iri),
577
+ functional: functional.has(iri),
578
+ reflexive: reflexive.has(iri),
579
+ irreflexive: irreflexive.has(iri),
580
+ asymmetric: asymmetric.has(iri),
581
+ ...commonAnnotations(a),
582
+ });
583
+ break;
584
+ default:
585
+ break;
586
+ }
587
+ }
588
+ // The ontology header, if present, becomes model-level metadata. The base IRI
589
+ // is best derived from an actual term's namespace (exact, delimiter and all);
590
+ // the ontology IRI is only a heuristic fallback (its own IRI often omits the
591
+ // trailing `#`/`/`), so use it only when no term supplied a namespace.
592
+ let ontology;
593
+ if (ontologyIri !== undefined) {
594
+ const a = annotations.get(ontologyIri) ?? emptyAnnotations();
595
+ const labels = a.label !== undefined ? [a.label, ...a.synonyms] : a.synonyms;
596
+ ontology = {
597
+ comment: descriptionOf(a),
598
+ synonyms: labels,
599
+ examples: a.examples,
600
+ version: a.versionInfo,
601
+ };
602
+ baseIri = baseIri ?? ontologyBaseIri(ontologyIri);
603
+ }
604
+ // Resolve each set-level-axiom node's `owl:members` list to its member IRIs.
605
+ // A node with no members list, or one whose list is broken/empty, contributes
606
+ // nothing (an axiom over no members is meaningless). Member names are kept as
607
+ // full IRIs; the mapper shortens an in-namespace one.
608
+ const resolveMembers = (nodes) => nodes.map(n => membersHead.get(n))
609
+ .filter((h) => h !== undefined)
610
+ .map(resolveList)
611
+ .filter(members => members.length > 0);
612
+ return {
613
+ baseIri,
614
+ ontology,
615
+ classes,
616
+ datatypeProperties,
617
+ objectProperties,
618
+ allDisjointClasses: resolveMembers(allDisjointClassesNodes),
619
+ allDisjointProperties: resolveMembers(allDisjointPropertiesNodes),
620
+ allDifferent: resolveMembers(allDifferentNodes),
621
+ };
622
+ }
623
+ // The base namespace an ontology IRI stands for. An owl:Ontology is commonly
624
+ // named by the namespace root without the trailing `#`/`/` (e.g.
625
+ // `http://example.com/sales`), so append `#` when the IRI has no delimiter of
626
+ // its own; otherwise keep it as given.
627
+ function ontologyBaseIri(iri) {
628
+ if (!iri)
629
+ return undefined;
630
+ const last = iri[iri.length - 1];
631
+ if (last === '#' || last === '/')
632
+ return iri;
633
+ return `${iri}#`;
634
+ }
@@ -0,0 +1,19 @@
1
+ import { SemanticModel } from '../../ir';
2
+ import { OwlModel } from './model';
3
+ export interface ToIrResult {
4
+ model: SemanticModel;
5
+ warnings: string[];
6
+ stats: {
7
+ classes: number;
8
+ datatypeProperties: number;
9
+ objectProperties: number;
10
+ };
11
+ }
12
+ /**
13
+ * Maps a parsed OwlModel to a Semantic Model IR (see ../../ir.ts).
14
+ *
15
+ * `modelName` names the resulting semantic model (the CLI derives it from the
16
+ * source filename). The IR it returns serializes, via osi_converter, to the
17
+ * OSI YAML shown in the user guide.
18
+ */
19
+ export declare function owlToIr(owl: OwlModel, modelName: string): ToIrResult;