cognite-neat 0.87.6__py3-none-any.whl → 0.88.0__py3-none-any.whl
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.
Potentially problematic release.
This version of cognite-neat might be problematic. Click here for more details.
- cognite/neat/_version.py +1 -1
- cognite/neat/app/api/data_classes/rest.py +0 -19
- cognite/neat/app/api/explorer.py +6 -4
- cognite/neat/app/api/routers/crud.py +11 -21
- cognite/neat/app/api/routers/workflows.py +24 -94
- cognite/neat/graph/stores/_base.py +5 -0
- cognite/neat/rules/importers/_inference2rules.py +31 -35
- cognite/neat/workflows/steps/data_contracts.py +17 -43
- cognite/neat/workflows/steps/lib/current/graph_extractor.py +28 -24
- cognite/neat/workflows/steps/lib/current/graph_loader.py +4 -21
- cognite/neat/workflows/steps/lib/current/graph_store.py +18 -134
- cognite/neat/workflows/steps_registry.py +5 -7
- {cognite_neat-0.87.6.dist-info → cognite_neat-0.88.0.dist-info}/METADATA +1 -1
- {cognite_neat-0.87.6.dist-info → cognite_neat-0.88.0.dist-info}/RECORD +17 -125
- cognite/neat/app/api/routers/core.py +0 -91
- cognite/neat/app/api/routers/data_exploration.py +0 -336
- cognite/neat/app/api/routers/rules.py +0 -203
- cognite/neat/legacy/__init__.py +0 -0
- cognite/neat/legacy/graph/__init__.py +0 -3
- cognite/neat/legacy/graph/examples/Knowledge-Graph-Nordic44-dirty.xml +0 -20182
- cognite/neat/legacy/graph/examples/Knowledge-Graph-Nordic44.xml +0 -20163
- cognite/neat/legacy/graph/examples/__init__.py +0 -10
- cognite/neat/legacy/graph/examples/skos-capturing-sheet-wind-topics.xlsx +0 -0
- cognite/neat/legacy/graph/exceptions.py +0 -90
- cognite/neat/legacy/graph/extractors/__init__.py +0 -6
- cognite/neat/legacy/graph/extractors/_base.py +0 -14
- cognite/neat/legacy/graph/extractors/_dexpi.py +0 -44
- cognite/neat/legacy/graph/extractors/_graph_capturing_sheet.py +0 -403
- cognite/neat/legacy/graph/extractors/_mock_graph_generator.py +0 -361
- cognite/neat/legacy/graph/loaders/__init__.py +0 -23
- cognite/neat/legacy/graph/loaders/_asset_loader.py +0 -511
- cognite/neat/legacy/graph/loaders/_base.py +0 -67
- cognite/neat/legacy/graph/loaders/_exceptions.py +0 -85
- cognite/neat/legacy/graph/loaders/core/__init__.py +0 -0
- cognite/neat/legacy/graph/loaders/core/labels.py +0 -58
- cognite/neat/legacy/graph/loaders/core/models.py +0 -136
- cognite/neat/legacy/graph/loaders/core/rdf_to_assets.py +0 -1046
- cognite/neat/legacy/graph/loaders/core/rdf_to_relationships.py +0 -559
- cognite/neat/legacy/graph/loaders/rdf_to_dms.py +0 -309
- cognite/neat/legacy/graph/loaders/validator.py +0 -87
- cognite/neat/legacy/graph/models.py +0 -6
- cognite/neat/legacy/graph/stores/__init__.py +0 -13
- cognite/neat/legacy/graph/stores/_base.py +0 -400
- cognite/neat/legacy/graph/stores/_graphdb_store.py +0 -52
- cognite/neat/legacy/graph/stores/_memory_store.py +0 -43
- cognite/neat/legacy/graph/stores/_oxigraph_store.py +0 -151
- cognite/neat/legacy/graph/stores/_oxrdflib.py +0 -247
- cognite/neat/legacy/graph/stores/_rdf_to_graph.py +0 -42
- cognite/neat/legacy/graph/transformations/__init__.py +0 -0
- cognite/neat/legacy/graph/transformations/entity_matcher.py +0 -101
- cognite/neat/legacy/graph/transformations/query_generator/__init__.py +0 -3
- cognite/neat/legacy/graph/transformations/query_generator/sparql.py +0 -575
- cognite/neat/legacy/graph/transformations/transformer.py +0 -322
- cognite/neat/legacy/rules/__init__.py +0 -0
- cognite/neat/legacy/rules/analysis.py +0 -231
- cognite/neat/legacy/rules/examples/Rules-Nordic44-to-graphql.xlsx +0 -0
- cognite/neat/legacy/rules/examples/Rules-Nordic44.xlsx +0 -0
- cognite/neat/legacy/rules/examples/__init__.py +0 -18
- cognite/neat/legacy/rules/examples/power-grid-containers.yaml +0 -124
- cognite/neat/legacy/rules/examples/power-grid-example.xlsx +0 -0
- cognite/neat/legacy/rules/examples/power-grid-model.yaml +0 -224
- cognite/neat/legacy/rules/examples/rules-template.xlsx +0 -0
- cognite/neat/legacy/rules/examples/sheet2cdf-transformation-rules.xlsx +0 -0
- cognite/neat/legacy/rules/examples/skos-rules.xlsx +0 -0
- cognite/neat/legacy/rules/examples/source-to-solution-mapping-rules.xlsx +0 -0
- cognite/neat/legacy/rules/examples/wind-energy.owl +0 -1511
- cognite/neat/legacy/rules/exceptions.py +0 -2972
- cognite/neat/legacy/rules/exporters/__init__.py +0 -20
- cognite/neat/legacy/rules/exporters/_base.py +0 -45
- cognite/neat/legacy/rules/exporters/_core/__init__.py +0 -5
- cognite/neat/legacy/rules/exporters/_core/rules2labels.py +0 -24
- cognite/neat/legacy/rules/exporters/_rules2dms.py +0 -885
- cognite/neat/legacy/rules/exporters/_rules2excel.py +0 -213
- cognite/neat/legacy/rules/exporters/_rules2graphql.py +0 -183
- cognite/neat/legacy/rules/exporters/_rules2ontology.py +0 -524
- cognite/neat/legacy/rules/exporters/_rules2pydantic_models.py +0 -748
- cognite/neat/legacy/rules/exporters/_rules2rules.py +0 -105
- cognite/neat/legacy/rules/exporters/_rules2triples.py +0 -38
- cognite/neat/legacy/rules/exporters/_validation.py +0 -146
- cognite/neat/legacy/rules/importers/__init__.py +0 -22
- cognite/neat/legacy/rules/importers/_base.py +0 -66
- cognite/neat/legacy/rules/importers/_dict2rules.py +0 -158
- cognite/neat/legacy/rules/importers/_dms2rules.py +0 -194
- cognite/neat/legacy/rules/importers/_graph2rules.py +0 -308
- cognite/neat/legacy/rules/importers/_json2rules.py +0 -39
- cognite/neat/legacy/rules/importers/_owl2rules/__init__.py +0 -3
- cognite/neat/legacy/rules/importers/_owl2rules/_owl2classes.py +0 -239
- cognite/neat/legacy/rules/importers/_owl2rules/_owl2metadata.py +0 -260
- cognite/neat/legacy/rules/importers/_owl2rules/_owl2properties.py +0 -217
- cognite/neat/legacy/rules/importers/_owl2rules/_owl2rules.py +0 -290
- cognite/neat/legacy/rules/importers/_spreadsheet2rules.py +0 -45
- cognite/neat/legacy/rules/importers/_xsd2rules.py +0 -20
- cognite/neat/legacy/rules/importers/_yaml2rules.py +0 -39
- cognite/neat/legacy/rules/models/__init__.py +0 -5
- cognite/neat/legacy/rules/models/_base.py +0 -151
- cognite/neat/legacy/rules/models/raw_rules.py +0 -316
- cognite/neat/legacy/rules/models/rdfpath.py +0 -237
- cognite/neat/legacy/rules/models/rules.py +0 -1289
- cognite/neat/legacy/rules/models/tables.py +0 -9
- cognite/neat/legacy/rules/models/value_types.py +0 -118
- cognite/neat/legacy/workflows/examples/Export_DMS/workflow.yaml +0 -89
- cognite/neat/legacy/workflows/examples/Export_Rules_to_Ontology/workflow.yaml +0 -152
- cognite/neat/legacy/workflows/examples/Extract_DEXPI_Graph_and_Export_Rules/workflow.yaml +0 -139
- cognite/neat/legacy/workflows/examples/Extract_RDF_Graph_and_Generate_Assets/workflow.yaml +0 -270
- cognite/neat/legacy/workflows/examples/Import_DMS/workflow.yaml +0 -65
- cognite/neat/legacy/workflows/examples/Ontology_to_Data_Model/workflow.yaml +0 -116
- cognite/neat/legacy/workflows/examples/Validate_Rules/workflow.yaml +0 -67
- cognite/neat/legacy/workflows/examples/Validate_Solution_Model/workflow.yaml +0 -64
- cognite/neat/legacy/workflows/examples/Visualize_Data_Model_Using_Mock_Graph/workflow.yaml +0 -95
- cognite/neat/legacy/workflows/examples/Visualize_Semantic_Data_Model/workflow.yaml +0 -111
- cognite/neat/workflows/examples/Extract_RDF_Graph_and_Generate_Assets/workflow.yaml +0 -270
- cognite/neat/workflows/migration/__init__.py +0 -0
- cognite/neat/workflows/migration/steps.py +0 -91
- cognite/neat/workflows/migration/wf_manifests.py +0 -33
- cognite/neat/workflows/steps/lib/legacy/__init__.py +0 -7
- cognite/neat/workflows/steps/lib/legacy/graph_contextualization.py +0 -82
- cognite/neat/workflows/steps/lib/legacy/graph_extractor.py +0 -746
- cognite/neat/workflows/steps/lib/legacy/graph_loader.py +0 -606
- cognite/neat/workflows/steps/lib/legacy/graph_store.py +0 -307
- cognite/neat/workflows/steps/lib/legacy/graph_transformer.py +0 -58
- cognite/neat/workflows/steps/lib/legacy/rules_exporter.py +0 -511
- cognite/neat/workflows/steps/lib/legacy/rules_importer.py +0 -612
- {cognite_neat-0.87.6.dist-info → cognite_neat-0.88.0.dist-info}/LICENSE +0 -0
- {cognite_neat-0.87.6.dist-info → cognite_neat-0.88.0.dist-info}/WHEEL +0 -0
- {cognite_neat-0.87.6.dist-info → cognite_neat-0.88.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,524 +0,0 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
import warnings
|
|
3
|
-
from abc import ABC
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import ClassVar
|
|
6
|
-
|
|
7
|
-
from pydantic import BaseModel, ConfigDict, ValidationInfo, field_validator
|
|
8
|
-
from rdflib import DCTERMS, OWL, RDF, RDFS, XSD, BNode, Graph, Literal, Namespace, URIRef
|
|
9
|
-
from rdflib.collection import Collection as GraphCollection
|
|
10
|
-
|
|
11
|
-
from cognite.neat.legacy.rules import exceptions
|
|
12
|
-
from cognite.neat.legacy.rules.analysis import to_class_property_pairs, to_property_dict
|
|
13
|
-
from cognite.neat.legacy.rules.exporters._base import BaseExporter
|
|
14
|
-
from cognite.neat.legacy.rules.exporters._validation import are_properties_redefined
|
|
15
|
-
from cognite.neat.legacy.rules.models.rules import Class, Metadata, Property, Rules
|
|
16
|
-
from cognite.neat.legacy.rules.models.value_types import XSD_VALUE_TYPE_MAPPINGS
|
|
17
|
-
from cognite.neat.utils.auxiliary import generate_exception_report
|
|
18
|
-
from cognite.neat.utils.rdf_ import remove_namespace_from_uri
|
|
19
|
-
|
|
20
|
-
if sys.version_info >= (3, 11):
|
|
21
|
-
from typing import Self
|
|
22
|
-
else:
|
|
23
|
-
from typing_extensions import Self
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class GraphExporter(BaseExporter[Graph], ABC):
|
|
27
|
-
def _export_to_file(self, filepath: Path) -> None:
|
|
28
|
-
self.export().serialize(destination=filepath)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class OWLExporter(GraphExporter):
|
|
32
|
-
def export(self) -> Graph:
|
|
33
|
-
return Ontology.from_rules(self.rules).as_owl()
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class SHACLExporter(GraphExporter):
|
|
37
|
-
def export(self) -> Graph:
|
|
38
|
-
return Ontology.from_rules(self.rules).as_shacl()
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class SemanticDataModelExporter(GraphExporter):
|
|
42
|
-
def export(self) -> Graph:
|
|
43
|
-
return Ontology.from_rules(self.rules).as_semantic_data_model()
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
class OntologyModel(BaseModel):
|
|
47
|
-
model_config: ClassVar[ConfigDict] = ConfigDict(arbitrary_types_allowed=True, strict=False, extra="allow")
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
class Ontology(OntologyModel):
|
|
51
|
-
"""
|
|
52
|
-
Represents an ontology. Thi class is used to generate an OWL ontology from a set of transformation rules.
|
|
53
|
-
|
|
54
|
-
Args:
|
|
55
|
-
properties: A list of OWL properties.
|
|
56
|
-
classes: A list of OWL classes.
|
|
57
|
-
shapes: A list of SHACL node shapes.
|
|
58
|
-
metadata: Metadata about the ontology.
|
|
59
|
-
prefixes: A dictionary of prefixes and namespaces.
|
|
60
|
-
"""
|
|
61
|
-
|
|
62
|
-
properties: list["OWLProperty"]
|
|
63
|
-
classes: list["OWLClass"]
|
|
64
|
-
shapes: list["SHACLNodeShape"]
|
|
65
|
-
metadata: "OWLMetadata"
|
|
66
|
-
prefixes: dict[str, Namespace]
|
|
67
|
-
|
|
68
|
-
@classmethod
|
|
69
|
-
def from_rules(cls, rules: Rules) -> Self:
|
|
70
|
-
"""
|
|
71
|
-
Generates an ontology from a set of transformation rules.
|
|
72
|
-
|
|
73
|
-
Args:
|
|
74
|
-
transformation_rules: Instance of TransformationRules.
|
|
75
|
-
|
|
76
|
-
Returns:
|
|
77
|
-
An instance of Ontology.
|
|
78
|
-
"""
|
|
79
|
-
properties_redefined, redefinition_warnings = are_properties_redefined(rules, return_report=True)
|
|
80
|
-
if properties_redefined:
|
|
81
|
-
raise exceptions.PropertiesDefinedMultipleTimes(report=generate_exception_report(redefinition_warnings))
|
|
82
|
-
|
|
83
|
-
if rules.prefixes is None:
|
|
84
|
-
raise exceptions.PrefixMissing()
|
|
85
|
-
|
|
86
|
-
if rules.metadata.namespace is None:
|
|
87
|
-
raise exceptions.MissingDataModelPrefixOrNamespace()
|
|
88
|
-
|
|
89
|
-
return cls(
|
|
90
|
-
properties=[
|
|
91
|
-
OWLProperty.from_list_of_properties(definition, rules.metadata.namespace)
|
|
92
|
-
for definition in to_property_dict(rules).values()
|
|
93
|
-
],
|
|
94
|
-
classes=[
|
|
95
|
-
OWLClass.from_class(definition, rules.metadata.namespace, rules.prefixes)
|
|
96
|
-
for definition in rules.classes.values()
|
|
97
|
-
],
|
|
98
|
-
shapes=[
|
|
99
|
-
SHACLNodeShape.from_rules(
|
|
100
|
-
rules.classes[class_],
|
|
101
|
-
list(properties.values()),
|
|
102
|
-
rules.metadata.namespace,
|
|
103
|
-
)
|
|
104
|
-
for class_, properties in to_class_property_pairs(rules).items()
|
|
105
|
-
],
|
|
106
|
-
metadata=OWLMetadata(**rules.metadata.model_dump()),
|
|
107
|
-
prefixes=rules.prefixes,
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
def as_shacl(self) -> Graph:
|
|
111
|
-
"""
|
|
112
|
-
Generates a SHACL graph from the ontology.
|
|
113
|
-
|
|
114
|
-
Returns:
|
|
115
|
-
A SHACL graph.
|
|
116
|
-
"""
|
|
117
|
-
|
|
118
|
-
shacl = Graph()
|
|
119
|
-
shacl.bind(self.metadata.prefix, self.metadata.namespace)
|
|
120
|
-
for prefix, namespace in self.prefixes.items():
|
|
121
|
-
shacl.bind(prefix, namespace)
|
|
122
|
-
|
|
123
|
-
for shape in self.shapes:
|
|
124
|
-
for triple in shape.triples:
|
|
125
|
-
shacl.add(triple) # type: ignore[arg-type]
|
|
126
|
-
|
|
127
|
-
return shacl
|
|
128
|
-
|
|
129
|
-
def as_owl(self) -> Graph:
|
|
130
|
-
"""
|
|
131
|
-
Generates an OWL graph from the ontology.
|
|
132
|
-
|
|
133
|
-
Returns:
|
|
134
|
-
An OWL graph.
|
|
135
|
-
"""
|
|
136
|
-
owl = Graph()
|
|
137
|
-
owl.bind(self.metadata.prefix, self.metadata.namespace)
|
|
138
|
-
for prefix, namespace in self.prefixes.items():
|
|
139
|
-
owl.bind(prefix, namespace)
|
|
140
|
-
|
|
141
|
-
if self.metadata.namespace is None:
|
|
142
|
-
raise exceptions.MetadataSheetNamespaceNotDefined()
|
|
143
|
-
|
|
144
|
-
owl.add((URIRef(self.metadata.namespace), RDF.type, OWL.Ontology))
|
|
145
|
-
for property_ in self.properties:
|
|
146
|
-
for triple in property_.triples:
|
|
147
|
-
owl.add(triple) # type: ignore[arg-type]
|
|
148
|
-
|
|
149
|
-
for class_ in self.classes:
|
|
150
|
-
for triple in class_.triples:
|
|
151
|
-
owl.add(triple) # type: ignore[arg-type]
|
|
152
|
-
|
|
153
|
-
for triple in self.metadata.triples:
|
|
154
|
-
owl.add(triple) # type: ignore[arg-type]
|
|
155
|
-
|
|
156
|
-
return owl
|
|
157
|
-
|
|
158
|
-
def as_semantic_data_model(self) -> Graph:
|
|
159
|
-
return self.as_owl() + self.as_shacl()
|
|
160
|
-
|
|
161
|
-
@property
|
|
162
|
-
def owl_triples(self) -> list[tuple]:
|
|
163
|
-
return list(self.as_owl())
|
|
164
|
-
|
|
165
|
-
@property
|
|
166
|
-
def shacl_triples(self) -> list[tuple]:
|
|
167
|
-
return list(self.as_shacl())
|
|
168
|
-
|
|
169
|
-
@property
|
|
170
|
-
def triples(self) -> list[tuple]:
|
|
171
|
-
return self.owl_triples + self.shacl_triples
|
|
172
|
-
|
|
173
|
-
@property
|
|
174
|
-
def ontology(self) -> str:
|
|
175
|
-
return self.as_owl().serialize()
|
|
176
|
-
|
|
177
|
-
@property
|
|
178
|
-
def constraints(self) -> str:
|
|
179
|
-
return self.as_shacl().serialize()
|
|
180
|
-
|
|
181
|
-
@property
|
|
182
|
-
def semantic_data_model(self) -> str:
|
|
183
|
-
return (self.as_owl() + self.as_shacl()).serialize()
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
class OWLMetadata(Metadata):
|
|
187
|
-
@property
|
|
188
|
-
def triples(self) -> list[tuple]:
|
|
189
|
-
# Mandatory triples originating from Metadata mandatory fields
|
|
190
|
-
if self.namespace is None:
|
|
191
|
-
raise exceptions.MetadataSheetNamespaceNotDefined()
|
|
192
|
-
triples: list[tuple] = [
|
|
193
|
-
(URIRef(self.namespace), DCTERMS.hasVersion, Literal(self.version)),
|
|
194
|
-
(URIRef(self.namespace), OWL.versionInfo, Literal(self.version)),
|
|
195
|
-
(URIRef(self.namespace), RDFS.label, Literal(self.name)),
|
|
196
|
-
(URIRef(self.namespace), DCTERMS.title, Literal(self.name)),
|
|
197
|
-
(URIRef(self.namespace), DCTERMS.created, Literal(self.created, datatype=XSD.dateTime)),
|
|
198
|
-
(URIRef(self.namespace), DCTERMS.description, Literal(self.description)),
|
|
199
|
-
]
|
|
200
|
-
if isinstance(self.creator, list):
|
|
201
|
-
triples.extend([(URIRef(self.namespace), DCTERMS.creator, Literal(creator)) for creator in self.creator])
|
|
202
|
-
else:
|
|
203
|
-
triples.append((URIRef(self.namespace), DCTERMS.creator, Literal(self.creator)))
|
|
204
|
-
|
|
205
|
-
# Optional triples originating from Metadata optional fields
|
|
206
|
-
if self.updated:
|
|
207
|
-
triples.append((URIRef(self.namespace), DCTERMS.modified, Literal(self.updated, datatype=XSD.dateTime)))
|
|
208
|
-
if self.rights:
|
|
209
|
-
triples.append((URIRef(self.namespace), DCTERMS.rights, Literal(self.rights)))
|
|
210
|
-
|
|
211
|
-
if self.contributor and isinstance(self.contributor, list):
|
|
212
|
-
triples.extend(
|
|
213
|
-
[
|
|
214
|
-
(URIRef(self.namespace), DCTERMS.contributor, Literal(contributor))
|
|
215
|
-
for contributor in self.contributor
|
|
216
|
-
]
|
|
217
|
-
)
|
|
218
|
-
elif self.contributor:
|
|
219
|
-
triples.append((URIRef(self.namespace), DCTERMS.contributor, Literal(self.contributor)))
|
|
220
|
-
|
|
221
|
-
return triples
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
class OWLClass(OntologyModel):
|
|
225
|
-
id_: URIRef
|
|
226
|
-
type_: URIRef = OWL.Class
|
|
227
|
-
label: str | None
|
|
228
|
-
comment: str | None
|
|
229
|
-
sub_class_of: list[URIRef] | None
|
|
230
|
-
namespace: Namespace
|
|
231
|
-
|
|
232
|
-
@classmethod
|
|
233
|
-
def from_class(cls, definition: Class, namespace: Namespace, prefixes: dict) -> Self:
|
|
234
|
-
if definition.parent_class and isinstance(definition.parent_class, list):
|
|
235
|
-
sub_class_of = []
|
|
236
|
-
for parent_class in definition.parent_class:
|
|
237
|
-
try:
|
|
238
|
-
sub_class_of.append(prefixes[parent_class.prefix][parent_class.suffix])
|
|
239
|
-
except KeyError:
|
|
240
|
-
sub_class_of.append(namespace[parent_class.suffix])
|
|
241
|
-
else:
|
|
242
|
-
sub_class_of = None
|
|
243
|
-
|
|
244
|
-
return cls(
|
|
245
|
-
id_=namespace[definition.class_id],
|
|
246
|
-
label=definition.class_name,
|
|
247
|
-
comment=definition.description,
|
|
248
|
-
sub_class_of=sub_class_of,
|
|
249
|
-
namespace=namespace,
|
|
250
|
-
)
|
|
251
|
-
|
|
252
|
-
@property
|
|
253
|
-
def type_triples(self) -> list[tuple]:
|
|
254
|
-
return [(self.id_, RDF.type, self.type_)]
|
|
255
|
-
|
|
256
|
-
@property
|
|
257
|
-
def label_triples(self) -> list[tuple]:
|
|
258
|
-
return [(self.id_, RDFS.label, Literal(self.label))]
|
|
259
|
-
|
|
260
|
-
@property
|
|
261
|
-
def comment_triples(self) -> list[tuple]:
|
|
262
|
-
return [(self.id_, RDFS.comment, Literal(self.comment))]
|
|
263
|
-
|
|
264
|
-
@property
|
|
265
|
-
def subclass_triples(self) -> list[tuple]:
|
|
266
|
-
if self.sub_class_of:
|
|
267
|
-
return [(self.id_, RDFS.subClassOf, sub_class_of) for sub_class_of in self.sub_class_of]
|
|
268
|
-
else:
|
|
269
|
-
return []
|
|
270
|
-
|
|
271
|
-
@property
|
|
272
|
-
def triples(self) -> list[tuple]:
|
|
273
|
-
return self.type_triples + self.label_triples + self.comment_triples + self.subclass_triples
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
class OWLProperty(OntologyModel):
|
|
277
|
-
id_: URIRef
|
|
278
|
-
type_: set[URIRef]
|
|
279
|
-
label: set[str]
|
|
280
|
-
comment: set[str]
|
|
281
|
-
domain: set[URIRef]
|
|
282
|
-
range_: set[URIRef]
|
|
283
|
-
namespace: Namespace
|
|
284
|
-
|
|
285
|
-
@staticmethod
|
|
286
|
-
def same_property_id(definitions: list[Property]) -> bool:
|
|
287
|
-
return len({definition.property_id for definition in definitions}) == 1
|
|
288
|
-
|
|
289
|
-
@classmethod
|
|
290
|
-
def from_list_of_properties(cls, definitions: list[Property], namespace: Namespace) -> "OWLProperty":
|
|
291
|
-
"""Here list of properties is a list of properties with the same id, but different definitions."""
|
|
292
|
-
|
|
293
|
-
if not cls.same_property_id(definitions):
|
|
294
|
-
raise exceptions.PropertyDefinitionsNotForSameProperty()
|
|
295
|
-
|
|
296
|
-
owl_property = cls.model_construct(
|
|
297
|
-
id_=namespace[definitions[0].property_id],
|
|
298
|
-
namespace=namespace,
|
|
299
|
-
label=set(),
|
|
300
|
-
comment=set(),
|
|
301
|
-
domain=set(),
|
|
302
|
-
range_=set(),
|
|
303
|
-
type_=set(),
|
|
304
|
-
)
|
|
305
|
-
for definition in definitions:
|
|
306
|
-
owl_property.type_.add(OWL[definition.property_type])
|
|
307
|
-
owl_property.range_.add(
|
|
308
|
-
XSD[definition.expected_value_type.suffix]
|
|
309
|
-
if definition.expected_value_type.suffix in XSD_VALUE_TYPE_MAPPINGS
|
|
310
|
-
else namespace[definition.expected_value_type.suffix]
|
|
311
|
-
)
|
|
312
|
-
owl_property.domain.add(namespace[definition.class_id])
|
|
313
|
-
|
|
314
|
-
if definition.property_name:
|
|
315
|
-
owl_property.label.add(definition.property_name)
|
|
316
|
-
if definition.description:
|
|
317
|
-
owl_property.comment.add(definition.description)
|
|
318
|
-
|
|
319
|
-
return owl_property
|
|
320
|
-
|
|
321
|
-
@field_validator("type_")
|
|
322
|
-
def is_multi_type(cls, v, info: ValidationInfo):
|
|
323
|
-
if len(v) > 1:
|
|
324
|
-
warnings.warn(
|
|
325
|
-
exceptions.OntologyMultiTypeProperty(
|
|
326
|
-
remove_namespace_from_uri(info.data["id_"]), [remove_namespace_from_uri(t) for t in v]
|
|
327
|
-
).message,
|
|
328
|
-
category=exceptions.OntologyMultiTypeProperty,
|
|
329
|
-
stacklevel=2,
|
|
330
|
-
)
|
|
331
|
-
return v
|
|
332
|
-
|
|
333
|
-
@field_validator("range_")
|
|
334
|
-
def is_multi_range(cls, v, info: ValidationInfo):
|
|
335
|
-
if len(v) > 1:
|
|
336
|
-
warnings.warn(
|
|
337
|
-
exceptions.OntologyMultiRangeProperty(
|
|
338
|
-
remove_namespace_from_uri(info.data["id_"]), [remove_namespace_from_uri(t) for t in v]
|
|
339
|
-
).message,
|
|
340
|
-
category=exceptions.OntologyMultiRangeProperty,
|
|
341
|
-
stacklevel=2,
|
|
342
|
-
)
|
|
343
|
-
return v
|
|
344
|
-
|
|
345
|
-
@field_validator("domain")
|
|
346
|
-
def is_multi_domain(cls, v, info: ValidationInfo):
|
|
347
|
-
if len(v) > 1:
|
|
348
|
-
warnings.warn(
|
|
349
|
-
exceptions.OntologyMultiDomainProperty(
|
|
350
|
-
remove_namespace_from_uri(info.data["id_"]), [remove_namespace_from_uri(t) for t in v]
|
|
351
|
-
).message,
|
|
352
|
-
category=exceptions.OntologyMultiDomainProperty,
|
|
353
|
-
stacklevel=2,
|
|
354
|
-
)
|
|
355
|
-
return v
|
|
356
|
-
|
|
357
|
-
@field_validator("label")
|
|
358
|
-
def has_multi_name(cls, v, info: ValidationInfo):
|
|
359
|
-
if len(v) > 1:
|
|
360
|
-
warnings.warn(
|
|
361
|
-
exceptions.OntologyMultiLabeledProperty(remove_namespace_from_uri(info.data["id_"]), v).message,
|
|
362
|
-
category=exceptions.OntologyMultiLabeledProperty,
|
|
363
|
-
stacklevel=2,
|
|
364
|
-
)
|
|
365
|
-
return v
|
|
366
|
-
|
|
367
|
-
@field_validator("comment")
|
|
368
|
-
def has_multi_comment(cls, v, info: ValidationInfo):
|
|
369
|
-
if len(v) > 1:
|
|
370
|
-
warnings.warn(
|
|
371
|
-
exceptions.OntologyMultiDefinitionProperty(remove_namespace_from_uri(info.data["id_"])).message,
|
|
372
|
-
category=exceptions.OntologyMultiDefinitionProperty,
|
|
373
|
-
stacklevel=2,
|
|
374
|
-
)
|
|
375
|
-
return v
|
|
376
|
-
|
|
377
|
-
@property
|
|
378
|
-
def domain_triples(self) -> list[tuple]:
|
|
379
|
-
triples: list[tuple] = []
|
|
380
|
-
if len(self.domain) == 1:
|
|
381
|
-
triples.append((self.id_, RDFS.domain, next(iter(self.domain))))
|
|
382
|
-
else:
|
|
383
|
-
_graph = Graph()
|
|
384
|
-
b_union = BNode()
|
|
385
|
-
b_domain = BNode()
|
|
386
|
-
_graph.add((self.id_, RDFS.domain, b_domain))
|
|
387
|
-
_graph.add((b_domain, OWL.unionOf, b_union))
|
|
388
|
-
_graph.add((b_domain, RDF.type, OWL.Class))
|
|
389
|
-
_ = GraphCollection(_graph, b_union, list(self.domain))
|
|
390
|
-
triples.extend(list(_graph))
|
|
391
|
-
return triples
|
|
392
|
-
|
|
393
|
-
@property
|
|
394
|
-
def range_triples(self) -> list[tuple]:
|
|
395
|
-
triples: list[tuple] = []
|
|
396
|
-
if len(self.range_) == 1:
|
|
397
|
-
triples.append((self.id_, RDFS.range, next(iter(self.range_))))
|
|
398
|
-
else:
|
|
399
|
-
_graph = Graph()
|
|
400
|
-
b_union = BNode()
|
|
401
|
-
b_range = BNode()
|
|
402
|
-
_graph.add((self.id_, RDFS.range, b_range))
|
|
403
|
-
_graph.add((b_range, OWL.unionOf, b_union))
|
|
404
|
-
_graph.add((b_range, RDF.type, OWL.Class))
|
|
405
|
-
_graph.add((b_range, OWL.unionOf, b_union))
|
|
406
|
-
_graph.add((b_range, RDF.type, OWL.Class))
|
|
407
|
-
_ = GraphCollection(_graph, b_union, list(self.range_))
|
|
408
|
-
triples.extend(list(_graph))
|
|
409
|
-
return triples
|
|
410
|
-
|
|
411
|
-
@property
|
|
412
|
-
def type_triples(self) -> list[tuple]:
|
|
413
|
-
return [(self.id_, RDF.type, type_) for type_ in self.type_]
|
|
414
|
-
|
|
415
|
-
@property
|
|
416
|
-
def label_triples(self) -> list[tuple]:
|
|
417
|
-
label = list(filter(None, self.label))
|
|
418
|
-
return [(self.id_, RDFS.label, Literal(label[0] if label else self.id_))]
|
|
419
|
-
|
|
420
|
-
@property
|
|
421
|
-
def comment_triples(self) -> list[tuple]:
|
|
422
|
-
return [(self.id_, RDFS.comment, Literal("\n".join(filter(None, self.comment))))]
|
|
423
|
-
|
|
424
|
-
@property
|
|
425
|
-
def triples(self) -> list[tuple]:
|
|
426
|
-
return self.type_triples + self.label_triples + self.comment_triples + self.domain_triples + self.range_triples
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
SHACL = Namespace("http://www.w3.org/ns/shacl#")
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
class SHACLNodeShape(OntologyModel):
|
|
433
|
-
id_: URIRef
|
|
434
|
-
type_: URIRef = SHACL.NodeShape
|
|
435
|
-
target_class: URIRef
|
|
436
|
-
property_shapes: list["SHACLPropertyShape"]
|
|
437
|
-
namespace: Namespace
|
|
438
|
-
|
|
439
|
-
@property
|
|
440
|
-
def type_triples(self) -> list[tuple]:
|
|
441
|
-
return [(self.id_, RDF.type, self.type_)]
|
|
442
|
-
|
|
443
|
-
@property
|
|
444
|
-
def target_class_triples(self) -> list[tuple]:
|
|
445
|
-
return [(self.id_, SHACL.targetClass, self.target_class)]
|
|
446
|
-
|
|
447
|
-
@property
|
|
448
|
-
def property_shapes_triples(self) -> list[tuple]:
|
|
449
|
-
triples: list[tuple] = []
|
|
450
|
-
for property_shape in self.property_shapes:
|
|
451
|
-
triples.append((self.id_, SHACL.property, property_shape.id_))
|
|
452
|
-
triples.extend(property_shape.triples)
|
|
453
|
-
return triples
|
|
454
|
-
|
|
455
|
-
@property
|
|
456
|
-
def triples(self) -> list[tuple]:
|
|
457
|
-
return self.type_triples + self.target_class_triples + self.property_shapes_triples
|
|
458
|
-
|
|
459
|
-
@classmethod
|
|
460
|
-
def from_rules(
|
|
461
|
-
cls, class_definition: Class, property_definitions: list[Property], namespace: Namespace
|
|
462
|
-
) -> "SHACLNodeShape":
|
|
463
|
-
return cls(
|
|
464
|
-
id_=namespace[f"{class_definition.class_id}Shape"],
|
|
465
|
-
target_class=namespace[class_definition.class_id],
|
|
466
|
-
property_shapes=[SHACLPropertyShape.from_property(prop, namespace) for prop in property_definitions],
|
|
467
|
-
namespace=namespace,
|
|
468
|
-
)
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
class SHACLPropertyShape(OntologyModel):
|
|
472
|
-
id_: BNode
|
|
473
|
-
type_: URIRef = SHACL.property
|
|
474
|
-
path: URIRef # URIRef to property in OWL
|
|
475
|
-
node_kind: URIRef # SHACL.IRI or SHACL.Literal
|
|
476
|
-
expected_value_type: URIRef
|
|
477
|
-
min_count: int | None
|
|
478
|
-
max_count: int | None
|
|
479
|
-
namespace: Namespace
|
|
480
|
-
|
|
481
|
-
@property
|
|
482
|
-
def path_triples(self) -> list[tuple]:
|
|
483
|
-
return [(self.id_, SHACL.path, self.path)]
|
|
484
|
-
|
|
485
|
-
@property
|
|
486
|
-
def node_kind_triples(self) -> list[tuple]:
|
|
487
|
-
triples: list[tuple] = [(self.id_, SHACL.nodeKind, self.node_kind)]
|
|
488
|
-
|
|
489
|
-
if self.node_kind == SHACL.Literal:
|
|
490
|
-
triples.append((self.id_, SHACL.datatype, self.expected_value_type))
|
|
491
|
-
else:
|
|
492
|
-
triples.append((self.id_, SHACL.node, self.expected_value_type))
|
|
493
|
-
|
|
494
|
-
return triples
|
|
495
|
-
|
|
496
|
-
@property
|
|
497
|
-
def cardinality_triples(self) -> list[tuple]:
|
|
498
|
-
triples: list[tuple] = []
|
|
499
|
-
if self.min_count:
|
|
500
|
-
triples.append((self.id_, SHACL.minCount, Literal(self.min_count)))
|
|
501
|
-
if self.max_count:
|
|
502
|
-
triples.append((self.id_, SHACL.maxCount, Literal(self.max_count)))
|
|
503
|
-
|
|
504
|
-
return triples
|
|
505
|
-
|
|
506
|
-
@property
|
|
507
|
-
def triples(self) -> list[tuple]:
|
|
508
|
-
return self.path_triples + self.node_kind_triples + self.cardinality_triples
|
|
509
|
-
|
|
510
|
-
@classmethod
|
|
511
|
-
def from_property(cls, definition: Property, namespace: Namespace) -> "SHACLPropertyShape":
|
|
512
|
-
return cls(
|
|
513
|
-
id_=BNode(),
|
|
514
|
-
path=namespace[definition.property_id],
|
|
515
|
-
node_kind=SHACL.IRI if definition.property_type == "ObjectProperty" else SHACL.Literal,
|
|
516
|
-
expected_value_type=(
|
|
517
|
-
namespace[f"{definition.expected_value_type.suffix}Shape"]
|
|
518
|
-
if definition.property_type == "ObjectProperty"
|
|
519
|
-
else XSD[definition.expected_value_type.suffix]
|
|
520
|
-
),
|
|
521
|
-
min_count=definition.min_count,
|
|
522
|
-
max_count=definition.max_count,
|
|
523
|
-
namespace=namespace,
|
|
524
|
-
)
|