personal_knowledge_library 3.0.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 personal_knowledge_library might be problematic. Click here for more details.
- knowledge/__init__.py +91 -0
- knowledge/base/__init__.py +22 -0
- knowledge/base/access.py +167 -0
- knowledge/base/entity.py +267 -0
- knowledge/base/language.py +27 -0
- knowledge/base/ontology.py +2734 -0
- knowledge/base/search.py +473 -0
- knowledge/base/tenant.py +192 -0
- knowledge/nel/__init__.py +11 -0
- knowledge/nel/base.py +495 -0
- knowledge/nel/engine.py +123 -0
- knowledge/ontomapping/__init__.py +667 -0
- knowledge/ontomapping/manager.py +320 -0
- knowledge/public/__init__.py +27 -0
- knowledge/public/cache.py +115 -0
- knowledge/public/helper.py +373 -0
- knowledge/public/relations.py +128 -0
- knowledge/public/wikidata.py +1324 -0
- knowledge/services/__init__.py +128 -0
- knowledge/services/asyncio/__init__.py +7 -0
- knowledge/services/asyncio/base.py +458 -0
- knowledge/services/asyncio/graph.py +1420 -0
- knowledge/services/asyncio/group.py +450 -0
- knowledge/services/asyncio/search.py +439 -0
- knowledge/services/asyncio/users.py +270 -0
- knowledge/services/base.py +533 -0
- knowledge/services/graph.py +1897 -0
- knowledge/services/group.py +819 -0
- knowledge/services/helper.py +142 -0
- knowledge/services/ontology.py +1234 -0
- knowledge/services/search.py +488 -0
- knowledge/services/session.py +444 -0
- knowledge/services/tenant.py +281 -0
- knowledge/services/users.py +445 -0
- knowledge/utils/__init__.py +10 -0
- knowledge/utils/graph.py +417 -0
- knowledge/utils/wikidata.py +197 -0
- knowledge/utils/wikipedia.py +175 -0
- personal_knowledge_library-3.0.0.dist-info/LICENSE +201 -0
- personal_knowledge_library-3.0.0.dist-info/METADATA +1163 -0
- personal_knowledge_library-3.0.0.dist-info/RECORD +42 -0
- personal_knowledge_library-3.0.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,2734 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright © 2021-present Wacom. All rights reserved.
|
|
3
|
+
import abc
|
|
4
|
+
import enum
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from json import JSONEncoder
|
|
7
|
+
from typing import Union, Optional, Any, List, Dict, Tuple, Set
|
|
8
|
+
|
|
9
|
+
import loguru
|
|
10
|
+
from rdflib import Literal, RDFS, OWL, URIRef, RDF, Graph
|
|
11
|
+
|
|
12
|
+
from knowledge.base.access import TenantAccessRight
|
|
13
|
+
from knowledge.base.entity import (
|
|
14
|
+
EntityStatus,
|
|
15
|
+
Label,
|
|
16
|
+
Description,
|
|
17
|
+
URI_TAG,
|
|
18
|
+
IMAGE_TAG,
|
|
19
|
+
DESCRIPTIONS_TAG,
|
|
20
|
+
LABELS_TAG,
|
|
21
|
+
TYPE_TAG,
|
|
22
|
+
STATUS_FLAG_TAG,
|
|
23
|
+
DATA_PROPERTIES_TAG,
|
|
24
|
+
OBJECT_PROPERTIES_TAG,
|
|
25
|
+
GROUP_IDS,
|
|
26
|
+
OWNER_TAG,
|
|
27
|
+
OWNER_ID_TAG,
|
|
28
|
+
SOURCE_REFERENCE_ID_TAG,
|
|
29
|
+
SOURCE_SYSTEM_TAG,
|
|
30
|
+
TENANT_RIGHTS_TAG,
|
|
31
|
+
LOCALE_TAG,
|
|
32
|
+
IS_MAIN_TAG,
|
|
33
|
+
USE_NEL_TAG,
|
|
34
|
+
VALUE_TAG,
|
|
35
|
+
DATA_PROPERTY_TAG,
|
|
36
|
+
VISIBILITY_TAG,
|
|
37
|
+
INFLECTION_CASE_SENSITIVE,
|
|
38
|
+
INFLECTION_SETTING,
|
|
39
|
+
INFLECTION_CONCEPT_CLASS,
|
|
40
|
+
LANGUAGE_TAG,
|
|
41
|
+
CONTENT_TAG,
|
|
42
|
+
DATA_TYPE_TAG,
|
|
43
|
+
RELATION_TAG,
|
|
44
|
+
INCOMING_TAG,
|
|
45
|
+
OUTGOING_TAG,
|
|
46
|
+
COMMENT_TAG,
|
|
47
|
+
LocalizedContent,
|
|
48
|
+
COMMENTS_TAG,
|
|
49
|
+
USE_VECTOR_INDEX_TAG,
|
|
50
|
+
SEND_VECTOR_INDEX_TAG,
|
|
51
|
+
USE_FULLTEXT_TAG,
|
|
52
|
+
TARGETS_TAG,
|
|
53
|
+
INDEXING_NEL_TARGET,
|
|
54
|
+
INDEXING_VECTOR_SEARCH_TARGET,
|
|
55
|
+
INDEXING_FULLTEXT_TARGET,
|
|
56
|
+
USE_VECTOR_DOCUMENT_INDEX_TAG,
|
|
57
|
+
INDEXING_VECTOR_SEARCH_DOCUMENT_TARGET,
|
|
58
|
+
EXTERNAL_USER_ID_TAG,
|
|
59
|
+
DESCRIPTION_TAG,
|
|
60
|
+
)
|
|
61
|
+
from knowledge.base.language import EN_US, SUPPORTED_LOCALES, EN, LanguageCode, LocaleCode
|
|
62
|
+
|
|
63
|
+
# ---------------------------------------------- Vocabulary base URI ---------------------------------------------------
|
|
64
|
+
PREFIX: str = "xsd"
|
|
65
|
+
BASE_URI: str = "http://www.w3.org/2001/XMLSchema#"
|
|
66
|
+
RESOURCE: str = "http://www.w3.org/2000/01/rdf-schema#Resource"
|
|
67
|
+
# ---------------------------------------------------- Constants -------------------------------------------------------
|
|
68
|
+
SUB_CLASS_OF_TAG: str = "subClassOf"
|
|
69
|
+
TENANT_ID: str = "tenantId"
|
|
70
|
+
NAME_TAG: str = "name"
|
|
71
|
+
SEND_TO_NEL: str = "sendToNEL"
|
|
72
|
+
# ---------------------------------------------------- RDFLib ----------------------------------------------------------
|
|
73
|
+
PREFERRED_LABEL: URIRef = URIRef("wacom:core#prefLabel")
|
|
74
|
+
logger = loguru.logger
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# ---------------------------------------------------- Ontology --------------------------------------------------------
|
|
78
|
+
class PropertyType(enum.Enum):
|
|
79
|
+
"""
|
|
80
|
+
PropertyType
|
|
81
|
+
-----------
|
|
82
|
+
Within the ontology two different property types are defined. A data- and an object property.
|
|
83
|
+
"""
|
|
84
|
+
|
|
85
|
+
OBJECT_PROPERTY = "Relation"
|
|
86
|
+
DATA_PROPERTY = "Literal"
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
INVERSE_PROPERTY_TYPE: Dict[str, PropertyType] = {pt.value: pt for pt in PropertyType}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class DataPropertyType(enum.Enum):
|
|
93
|
+
"""
|
|
94
|
+
DataPropertyType.
|
|
95
|
+
-----------------
|
|
96
|
+
Data types that are used by Datatype properties.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
STRING = BASE_URI + "string"
|
|
100
|
+
"""Character strings (but not all Unicode character strings) """
|
|
101
|
+
BOOLEAN = BASE_URI + "boolean"
|
|
102
|
+
"""boolean: true, false"""
|
|
103
|
+
DECIMAL = BASE_URI + "decimal"
|
|
104
|
+
"""Arbitrary-precision decimal numbers"""
|
|
105
|
+
INTEGER = BASE_URI + "integer"
|
|
106
|
+
"""Arbitrary-size integer numbers"""
|
|
107
|
+
DOUBLE = BASE_URI + "double"
|
|
108
|
+
"""64-bit floating point numbers incl. ±Inf, ±0, NaN"""
|
|
109
|
+
FLOAT = BASE_URI + "float"
|
|
110
|
+
"""32-bit floating point numbers incl. ±Inf, ±0, NaN"""
|
|
111
|
+
DATE = BASE_URI + "date"
|
|
112
|
+
"""Dates (yyyy-mm-dd) with or without timezone"""
|
|
113
|
+
TIME = BASE_URI + "time"
|
|
114
|
+
"""Times (hh:mm:ss.sss…) with or without timezone"""
|
|
115
|
+
DATE_TIME = BASE_URI + "dateTime"
|
|
116
|
+
"""Date and time with or without timezone"""
|
|
117
|
+
DATE_TIMESTAMP = BASE_URI + "dateTimeStamp"
|
|
118
|
+
"""Date and time with required timezone """
|
|
119
|
+
G_YEAR = BASE_URI + "gYear"
|
|
120
|
+
"""Gregorian calendar year"""
|
|
121
|
+
G_MONTH = BASE_URI + "gMonth"
|
|
122
|
+
"""Gregorian calendar month"""
|
|
123
|
+
G_DAY = BASE_URI + "gDay"
|
|
124
|
+
"""Gregorian calendar day of the month"""
|
|
125
|
+
G_YEAR_MONTH = BASE_URI + "gYearMonth"
|
|
126
|
+
"""Gregorian calendar year and month"""
|
|
127
|
+
G_MONTH_DAY = BASE_URI + "gMonthDay"
|
|
128
|
+
"""Gregorian calendar month and day"""
|
|
129
|
+
DURATION = BASE_URI + "duration"
|
|
130
|
+
"""Duration of time"""
|
|
131
|
+
YEAR_MONTH_DURATION = BASE_URI + "yearMonthDuration"
|
|
132
|
+
"""Duration of time (months and years only)"""
|
|
133
|
+
DAYTIME_DURATION = BASE_URI + "dayTimeDuration"
|
|
134
|
+
"""Duration of time (days, hours, minutes, seconds only)"""
|
|
135
|
+
BYTES = BASE_URI + "byte"
|
|
136
|
+
"""-128…+127 (8 bit)"""
|
|
137
|
+
SHORT = BASE_URI + "short"
|
|
138
|
+
"""-32768… + 32767 (16 bit)"""
|
|
139
|
+
INT = BASE_URI + "int"
|
|
140
|
+
"""-2147483648…+2147483647 (32 bit)"""
|
|
141
|
+
LONG = BASE_URI + "long"
|
|
142
|
+
"""-9223372036854775808…+9223372036854775807 (64 bit)"""
|
|
143
|
+
UNSIGNED_BYTE = BASE_URI + "unsignedByte"
|
|
144
|
+
"""0 … 255 (8 bit)"""
|
|
145
|
+
UNSIGNED_SHORT = BASE_URI + "unsignedShort"
|
|
146
|
+
"""0 … 65535 (16 bit)"""
|
|
147
|
+
UNSIGNED_INT = BASE_URI + "unsignedInt"
|
|
148
|
+
""" 0 … 4294967295 (32 bit)"""
|
|
149
|
+
UNSIGNED_LONG = BASE_URI + "unsignedLong"
|
|
150
|
+
""" 0 … 18446744073709551615 (64 bit)"""
|
|
151
|
+
POSITIVE_INTEGER = BASE_URI + "positiveInteger"
|
|
152
|
+
"""Integer numbers > 0 """
|
|
153
|
+
NON_NEGATIVE_INTEGER = BASE_URI + "nonNegativeInteger"
|
|
154
|
+
"""Integer numbers ≥ 0"""
|
|
155
|
+
NEGATIVE_INTEGER = BASE_URI + "negativeInteger"
|
|
156
|
+
"""Integer numbers ≤ 0"""
|
|
157
|
+
NON_POSITIVE_INTEGER = BASE_URI + "nonPositiveInteger"
|
|
158
|
+
"""Integer numbers ≤ 0"""
|
|
159
|
+
HEX_BINARY = BASE_URI + "hexBinary"
|
|
160
|
+
"""Hex-encoded binary data"""
|
|
161
|
+
BASE64_BINARY = BASE_URI + "base64Binary"
|
|
162
|
+
"""Base64-encoded binary data"""
|
|
163
|
+
ANY_URI = BASE_URI + "anyURI"
|
|
164
|
+
"""Absolute or relative URIs and IRIs"""
|
|
165
|
+
LANGUAGE = BASE_URI + "language_code"
|
|
166
|
+
"""Language tags per http://tools.ietf.org/html/bcp47"""
|
|
167
|
+
NORMALIZED = BASE_URI + "normalizedString"
|
|
168
|
+
"""Whitespace-normalized strings"""
|
|
169
|
+
TOKEN = BASE_URI + "token"
|
|
170
|
+
"""Tokenized strings"""
|
|
171
|
+
NM_TOKEN = BASE_URI + "NMTOKEN"
|
|
172
|
+
"""XML NMTOKENs"""
|
|
173
|
+
NAME = BASE_URI + "Name"
|
|
174
|
+
"""XML Names"""
|
|
175
|
+
NC_NAME = BASE_URI + "NCName"
|
|
176
|
+
"""XML NCNames"""
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
INVERSE_DATA_PROPERTY_TYPE_MAPPING: Dict[str, DataPropertyType] = {
|
|
180
|
+
str(lit_type.value): lit_type for lit_type in DataPropertyType
|
|
181
|
+
}
|
|
182
|
+
"""Maps the string representation of the XSD data types to the data types enum constants."""
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
# ------------------------------------------ Ontology References -------------------------------------------------------
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class OntologyLabel(LocalizedContent):
|
|
189
|
+
"""
|
|
190
|
+
Ontology Label
|
|
191
|
+
--------------
|
|
192
|
+
Label that is multilingual.
|
|
193
|
+
|
|
194
|
+
Parameters
|
|
195
|
+
----------
|
|
196
|
+
content: str
|
|
197
|
+
Content value
|
|
198
|
+
language_code: LanguageCode (default:= 'en')
|
|
199
|
+
Language code of content
|
|
200
|
+
main: bool (default:=False)
|
|
201
|
+
Main content
|
|
202
|
+
"""
|
|
203
|
+
|
|
204
|
+
def __init__(self, content: str, language_code: LanguageCode = EN, main: bool = False):
|
|
205
|
+
self.__main: bool = main
|
|
206
|
+
super().__init__(content, language_code)
|
|
207
|
+
|
|
208
|
+
@property
|
|
209
|
+
def main(self) -> bool:
|
|
210
|
+
"""Flag if the content is the main content or an alias."""
|
|
211
|
+
return self.__main
|
|
212
|
+
|
|
213
|
+
@staticmethod
|
|
214
|
+
def create_from_dict(
|
|
215
|
+
dict_label: Dict[str, Any], tag_name: str = CONTENT_TAG, locale_name: str = LOCALE_TAG
|
|
216
|
+
) -> "OntologyLabel":
|
|
217
|
+
"""
|
|
218
|
+
Create a label from a dictionary.
|
|
219
|
+
|
|
220
|
+
Parameters
|
|
221
|
+
----------
|
|
222
|
+
dict_label: Dict[str, Any]
|
|
223
|
+
Dictionary with the label information
|
|
224
|
+
tag_name: str
|
|
225
|
+
Tag name of the content
|
|
226
|
+
locale_name: str
|
|
227
|
+
Tag name of the language code
|
|
228
|
+
|
|
229
|
+
Returns
|
|
230
|
+
-------
|
|
231
|
+
instance: OntologyLabel
|
|
232
|
+
Instance of the label
|
|
233
|
+
"""
|
|
234
|
+
if tag_name not in dict_label:
|
|
235
|
+
raise ValueError("Dict is does not contain a localized label.")
|
|
236
|
+
if locale_name not in dict_label:
|
|
237
|
+
raise ValueError("Dict is does not contain a language code")
|
|
238
|
+
if IS_MAIN_TAG in dict_label:
|
|
239
|
+
return OntologyLabel(dict_label[tag_name], LanguageCode(dict_label[locale_name]), dict_label[IS_MAIN_TAG])
|
|
240
|
+
return OntologyLabel(dict_label[tag_name], LanguageCode(dict_label[locale_name]))
|
|
241
|
+
|
|
242
|
+
@staticmethod
|
|
243
|
+
def create_from_list(param: List[dict]) -> List["OntologyLabel"]:
|
|
244
|
+
"""
|
|
245
|
+
Create a list of labels from a list of dictionaries.
|
|
246
|
+
Parameters
|
|
247
|
+
----------
|
|
248
|
+
param: List[dict]
|
|
249
|
+
List of dictionaries with the label information
|
|
250
|
+
|
|
251
|
+
Returns
|
|
252
|
+
-------
|
|
253
|
+
instances: List[OntologyLabel]
|
|
254
|
+
List of label instances
|
|
255
|
+
"""
|
|
256
|
+
return [OntologyLabel.create_from_dict(p) for p in param]
|
|
257
|
+
|
|
258
|
+
def __dict__(self):
|
|
259
|
+
return {CONTENT_TAG: self.content, LOCALE_TAG: self.language_code, IS_MAIN_TAG: self.main}
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
class OntologyObjectReference(abc.ABC):
|
|
263
|
+
"""
|
|
264
|
+
Ontology class type
|
|
265
|
+
------------------
|
|
266
|
+
Associated to an entity to link the type of the entity.
|
|
267
|
+
|
|
268
|
+
Parameters
|
|
269
|
+
----------
|
|
270
|
+
scheme: str
|
|
271
|
+
Scheme or owner of the ontology object
|
|
272
|
+
context: str
|
|
273
|
+
Context of ontology object
|
|
274
|
+
name: str
|
|
275
|
+
Ontology object reference name
|
|
276
|
+
"""
|
|
277
|
+
|
|
278
|
+
def __init__(self, scheme: str, context: str, name: str):
|
|
279
|
+
self.__scheme: str = scheme
|
|
280
|
+
self.__context: str = context
|
|
281
|
+
self.__name: str = name
|
|
282
|
+
|
|
283
|
+
@property
|
|
284
|
+
def scheme(self):
|
|
285
|
+
"""Scheme."""
|
|
286
|
+
return self.__scheme
|
|
287
|
+
|
|
288
|
+
@property
|
|
289
|
+
def context(self):
|
|
290
|
+
"""Context."""
|
|
291
|
+
return self.__context
|
|
292
|
+
|
|
293
|
+
@property
|
|
294
|
+
def name(self):
|
|
295
|
+
"""Name."""
|
|
296
|
+
return self.__name
|
|
297
|
+
|
|
298
|
+
@property
|
|
299
|
+
def iri(self):
|
|
300
|
+
"""Internationalized Resource Identifier (IRI) encoded ontology class name."""
|
|
301
|
+
return f"{self.scheme}:{self.context}#{self.name}"
|
|
302
|
+
|
|
303
|
+
def __repr__(self):
|
|
304
|
+
return self.iri
|
|
305
|
+
|
|
306
|
+
@classmethod
|
|
307
|
+
def parse_iri(cls, iri: str) -> Tuple[str, str, str]:
|
|
308
|
+
"""Parse an IRI into its components.
|
|
309
|
+
|
|
310
|
+
Parameters
|
|
311
|
+
----------
|
|
312
|
+
iri: str
|
|
313
|
+
IRI to parse
|
|
314
|
+
|
|
315
|
+
Returns
|
|
316
|
+
-------
|
|
317
|
+
Tuple[str, str, str]
|
|
318
|
+
Scheme, context and name of the IRI
|
|
319
|
+
"""
|
|
320
|
+
if iri is None:
|
|
321
|
+
raise ValueError("IRI cannot be None")
|
|
322
|
+
if ":" not in iri or "#" not in iri:
|
|
323
|
+
raise ValueError(f"Invalid IRI: {iri}")
|
|
324
|
+
colon_idx: int = iri.index(":")
|
|
325
|
+
hash_idx: int = iri.index("#")
|
|
326
|
+
scheme: str = iri[:colon_idx]
|
|
327
|
+
context: str = iri[colon_idx + 1 : hash_idx]
|
|
328
|
+
name: str = iri[hash_idx + 1 :]
|
|
329
|
+
return scheme, context, name
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
class OntologyClassReference(OntologyObjectReference):
|
|
333
|
+
"""
|
|
334
|
+
Ontology class type
|
|
335
|
+
-------------------
|
|
336
|
+
Associated to an ontology class.
|
|
337
|
+
|
|
338
|
+
Parameters
|
|
339
|
+
----------
|
|
340
|
+
scheme: str
|
|
341
|
+
Scheme or owner
|
|
342
|
+
context: str
|
|
343
|
+
Context of class
|
|
344
|
+
class_name: str
|
|
345
|
+
Class name
|
|
346
|
+
"""
|
|
347
|
+
|
|
348
|
+
def __init__(self, scheme: str, context: str, class_name: str):
|
|
349
|
+
super().__init__(scheme, context, class_name)
|
|
350
|
+
|
|
351
|
+
@property
|
|
352
|
+
def class_name(self):
|
|
353
|
+
"""Class name."""
|
|
354
|
+
return self.name
|
|
355
|
+
|
|
356
|
+
@classmethod
|
|
357
|
+
def parse(cls, iri: str) -> "OntologyClassReference":
|
|
358
|
+
"""Parse IRI to create an ontology class reference.
|
|
359
|
+
|
|
360
|
+
Parameters
|
|
361
|
+
----------
|
|
362
|
+
iri: str
|
|
363
|
+
IRI of ontology class reference
|
|
364
|
+
|
|
365
|
+
Returns
|
|
366
|
+
-------
|
|
367
|
+
instance: OntologyClassReference
|
|
368
|
+
Instance of ontology class reference
|
|
369
|
+
"""
|
|
370
|
+
scheme, context, name = OntologyObjectReference.parse_iri(iri)
|
|
371
|
+
return OntologyClassReference(scheme, context, name)
|
|
372
|
+
|
|
373
|
+
def __eq__(self, other):
|
|
374
|
+
if not isinstance(other, OntologyClassReference):
|
|
375
|
+
return False
|
|
376
|
+
return self.iri == other.iri
|
|
377
|
+
|
|
378
|
+
def __hash__(self):
|
|
379
|
+
return hash(self.iri)
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
class OntologyPropertyReference(OntologyObjectReference):
|
|
383
|
+
"""
|
|
384
|
+
Property reference
|
|
385
|
+
------------------
|
|
386
|
+
Associated to an ontology property.
|
|
387
|
+
|
|
388
|
+
Parameters
|
|
389
|
+
----------
|
|
390
|
+
scheme: str
|
|
391
|
+
Scheme or owner
|
|
392
|
+
context: str
|
|
393
|
+
Context of class
|
|
394
|
+
property_name: str
|
|
395
|
+
Property name
|
|
396
|
+
"""
|
|
397
|
+
|
|
398
|
+
def __init__(self, scheme: str, context: str, property_name: str):
|
|
399
|
+
super().__init__(scheme, context, property_name)
|
|
400
|
+
|
|
401
|
+
@property
|
|
402
|
+
def property_name(self):
|
|
403
|
+
"""Property name."""
|
|
404
|
+
return self.name
|
|
405
|
+
|
|
406
|
+
@classmethod
|
|
407
|
+
def parse(cls, iri: str) -> "OntologyPropertyReference":
|
|
408
|
+
"""Parses an IRI into an OntologyPropertyReference.
|
|
409
|
+
|
|
410
|
+
Parameters
|
|
411
|
+
----------
|
|
412
|
+
iri: str
|
|
413
|
+
IRI to parse
|
|
414
|
+
|
|
415
|
+
Returns
|
|
416
|
+
-------
|
|
417
|
+
instance: OntologyPropertyReference
|
|
418
|
+
Instance of OntologyPropertyReference
|
|
419
|
+
"""
|
|
420
|
+
scheme, context, name = OntologyObjectReference.parse_iri(iri)
|
|
421
|
+
return OntologyPropertyReference(scheme, context, name)
|
|
422
|
+
|
|
423
|
+
def __eq__(self, other):
|
|
424
|
+
if not isinstance(other, OntologyPropertyReference):
|
|
425
|
+
return False
|
|
426
|
+
return self.iri == other.iri
|
|
427
|
+
|
|
428
|
+
def __hash__(self):
|
|
429
|
+
return hash(self.iri)
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
# ---------------------------------------------------- Classes Constants -----------------------------------------------
|
|
433
|
+
THING_CLASS: OntologyClassReference = OntologyClassReference("wacom", "core", "Thing")
|
|
434
|
+
# ---------------------------------------------------- Property Constants ----------------------------------------------
|
|
435
|
+
SYSTEM_SOURCE_SYSTEM: OntologyPropertyReference = OntologyPropertyReference("wacom", "core", "sourceSystem")
|
|
436
|
+
SYSTEM_SOURCE_REFERENCE_ID: OntologyPropertyReference = OntologyPropertyReference("wacom", "core", "sourceReferenceId")
|
|
437
|
+
CREATION_DATE: OntologyPropertyReference = OntologyPropertyReference.parse("wacom:core#creationDate")
|
|
438
|
+
LAST_UPDATE_DATE: OntologyPropertyReference = OntologyPropertyReference.parse("wacom:core#lastUpdate")
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
class Comment(LocalizedContent):
|
|
442
|
+
"""
|
|
443
|
+
Comment
|
|
444
|
+
-------
|
|
445
|
+
Comment that is multi-lingual.
|
|
446
|
+
|
|
447
|
+
Parameters
|
|
448
|
+
----------
|
|
449
|
+
text: str
|
|
450
|
+
Text value
|
|
451
|
+
language_code: LanguageCode (default:= 'en')
|
|
452
|
+
Language code of content
|
|
453
|
+
"""
|
|
454
|
+
|
|
455
|
+
def __init__(self, text: str, language_code: LanguageCode = "en"):
|
|
456
|
+
super().__init__(text, language_code)
|
|
457
|
+
|
|
458
|
+
@staticmethod
|
|
459
|
+
def create_from_dict(dict_description: Dict[str, Any]) -> "Comment":
|
|
460
|
+
"""
|
|
461
|
+
Create a comment from a dictionary.
|
|
462
|
+
Parameters
|
|
463
|
+
----------
|
|
464
|
+
dict_description: Dict[str, Any]
|
|
465
|
+
Dictionary containing the comment
|
|
466
|
+
|
|
467
|
+
Returns
|
|
468
|
+
-------
|
|
469
|
+
instance: Comment
|
|
470
|
+
Instance of comment
|
|
471
|
+
"""
|
|
472
|
+
if VALUE_TAG not in dict_description or LANGUAGE_TAG not in dict_description:
|
|
473
|
+
raise ValueError("Dict is does not contain a localized comment.")
|
|
474
|
+
return Comment(dict_description[VALUE_TAG], dict_description[LANGUAGE_TAG])
|
|
475
|
+
|
|
476
|
+
@staticmethod
|
|
477
|
+
def create_from_list(param: List[Dict[str, Any]]) -> List["Comment"]:
|
|
478
|
+
"""
|
|
479
|
+
Create a list of comments from a list of dictionaries.
|
|
480
|
+
Parameters
|
|
481
|
+
----------
|
|
482
|
+
param: List[Dict[str, Any]]
|
|
483
|
+
List of dictionaries containing the comments
|
|
484
|
+
|
|
485
|
+
Returns
|
|
486
|
+
-------
|
|
487
|
+
instances: List[Comment]
|
|
488
|
+
List of instances of comments
|
|
489
|
+
"""
|
|
490
|
+
return [Comment.create_from_dict(p) for p in param]
|
|
491
|
+
|
|
492
|
+
def __dict__(self):
|
|
493
|
+
return {
|
|
494
|
+
COMMENT_TAG: self.content,
|
|
495
|
+
LOCALE_TAG: self.language_code,
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
class OntologyObject(abc.ABC):
|
|
500
|
+
"""
|
|
501
|
+
Generic ontology object
|
|
502
|
+
-----------------------
|
|
503
|
+
|
|
504
|
+
Parameters
|
|
505
|
+
----------
|
|
506
|
+
tenant_id: str
|
|
507
|
+
Reference id for tenant
|
|
508
|
+
iri: str
|
|
509
|
+
IRI of the ontology object
|
|
510
|
+
icon: str
|
|
511
|
+
Icon assigned to object, visually representing it
|
|
512
|
+
labels: List[Label]
|
|
513
|
+
List of multi-language_code labels
|
|
514
|
+
comments: List[Label]
|
|
515
|
+
List of multi-language_code comments
|
|
516
|
+
context: str
|
|
517
|
+
Context
|
|
518
|
+
"""
|
|
519
|
+
|
|
520
|
+
def __init__(
|
|
521
|
+
self, tenant_id: str, iri: str, icon: str, labels: List[OntologyLabel], comments: List[Comment], context: str
|
|
522
|
+
):
|
|
523
|
+
self.__tenant_id: str = tenant_id
|
|
524
|
+
self.__labels: List[OntologyLabel] = labels
|
|
525
|
+
self.__comments: List[Comment] = comments
|
|
526
|
+
self.__iri: str = iri
|
|
527
|
+
self.__icon: str = icon
|
|
528
|
+
self.__context: str = context
|
|
529
|
+
|
|
530
|
+
@property
|
|
531
|
+
def tenant_id(self) -> str:
|
|
532
|
+
"""Tenant id."""
|
|
533
|
+
return self.__tenant_id
|
|
534
|
+
|
|
535
|
+
@property
|
|
536
|
+
def iri(self) -> str:
|
|
537
|
+
"""IRI"""
|
|
538
|
+
return self.__iri
|
|
539
|
+
|
|
540
|
+
@property
|
|
541
|
+
def context(self) -> str:
|
|
542
|
+
"""Context."""
|
|
543
|
+
return self.__context
|
|
544
|
+
|
|
545
|
+
@property
|
|
546
|
+
def icon(self) -> str:
|
|
547
|
+
"""Icon."""
|
|
548
|
+
return self.__icon
|
|
549
|
+
|
|
550
|
+
@icon.setter
|
|
551
|
+
def icon(self, value: str):
|
|
552
|
+
self.__icon = value
|
|
553
|
+
|
|
554
|
+
@property
|
|
555
|
+
def labels(self) -> List[OntologyLabel]:
|
|
556
|
+
"""Labels related to ontology object."""
|
|
557
|
+
return self.__labels
|
|
558
|
+
|
|
559
|
+
def label_for_lang(self, language_code: LanguageCode) -> Optional[OntologyLabel]:
|
|
560
|
+
"""
|
|
561
|
+
Get label for language_code.
|
|
562
|
+
Parameters
|
|
563
|
+
----------
|
|
564
|
+
language_code: LanguageCode
|
|
565
|
+
Language code
|
|
566
|
+
|
|
567
|
+
Returns
|
|
568
|
+
-------
|
|
569
|
+
label: Optional[OntologyLabel]
|
|
570
|
+
Label for language_code
|
|
571
|
+
"""
|
|
572
|
+
for label in self.labels:
|
|
573
|
+
if label.language_code == language_code:
|
|
574
|
+
return label
|
|
575
|
+
return None
|
|
576
|
+
|
|
577
|
+
@property
|
|
578
|
+
def comments(self) -> List[Comment]:
|
|
579
|
+
"""Comment related to ontology object."""
|
|
580
|
+
return self.__comments
|
|
581
|
+
|
|
582
|
+
def comment_for_lang(self, language_code: LanguageCode) -> Optional[Comment]:
|
|
583
|
+
"""
|
|
584
|
+
Get comment for language_code.
|
|
585
|
+
Parameters
|
|
586
|
+
----------
|
|
587
|
+
language_code: LanguageCode
|
|
588
|
+
Language code
|
|
589
|
+
|
|
590
|
+
Returns
|
|
591
|
+
-------
|
|
592
|
+
comment: Optional[Comment]
|
|
593
|
+
Comment for language_code
|
|
594
|
+
"""
|
|
595
|
+
for comment in self.comments:
|
|
596
|
+
if comment.language_code == language_code:
|
|
597
|
+
return comment
|
|
598
|
+
return None
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
class OntologyContextSettings:
|
|
602
|
+
"""
|
|
603
|
+
OntologyContextSettings
|
|
604
|
+
-----------------------
|
|
605
|
+
Describes the settings of the context, such as:
|
|
606
|
+
- prefixes for RDF, RDFS and OWL
|
|
607
|
+
- Base literal URI
|
|
608
|
+
- Base class URI
|
|
609
|
+
- Description literal name
|
|
610
|
+
- depth
|
|
611
|
+
"""
|
|
612
|
+
|
|
613
|
+
def __init__(
|
|
614
|
+
self,
|
|
615
|
+
rdf_prefix: str,
|
|
616
|
+
rdfs_prefix: str,
|
|
617
|
+
owl_prefix: str,
|
|
618
|
+
base_literal_uri: str,
|
|
619
|
+
base_class_uri: str,
|
|
620
|
+
description_literal_name: str,
|
|
621
|
+
depth: int,
|
|
622
|
+
):
|
|
623
|
+
self.__rdf_prefix: str = rdf_prefix
|
|
624
|
+
self.__rdfs_prefix: str = rdfs_prefix
|
|
625
|
+
self.__owl_prefix: str = owl_prefix
|
|
626
|
+
self.__base_literal_uri: str = base_literal_uri
|
|
627
|
+
self.__base_class_uri: str = base_class_uri
|
|
628
|
+
self.__description_literal_name: str = description_literal_name
|
|
629
|
+
self.__depth: int = depth
|
|
630
|
+
|
|
631
|
+
@property
|
|
632
|
+
def rdf_prefix(self):
|
|
633
|
+
"""RDF prefix"""
|
|
634
|
+
return self.__rdf_prefix
|
|
635
|
+
|
|
636
|
+
@property
|
|
637
|
+
def rdfs_prefix(self):
|
|
638
|
+
"""RDFS prefix"""
|
|
639
|
+
return self.__rdfs_prefix
|
|
640
|
+
|
|
641
|
+
@property
|
|
642
|
+
def owl_prefix(self):
|
|
643
|
+
"""OWL prefix"""
|
|
644
|
+
return self.__owl_prefix
|
|
645
|
+
|
|
646
|
+
@property
|
|
647
|
+
def base_literal_uri(self):
|
|
648
|
+
"""Base literal URI."""
|
|
649
|
+
return self.__base_literal_uri
|
|
650
|
+
|
|
651
|
+
@property
|
|
652
|
+
def base_class_uri(self):
|
|
653
|
+
"""Base class URI."""
|
|
654
|
+
return self.__base_class_uri
|
|
655
|
+
|
|
656
|
+
@property
|
|
657
|
+
def description_literal_name(self) -> str:
|
|
658
|
+
"""Literal name of the description."""
|
|
659
|
+
return self.__description_literal_name
|
|
660
|
+
|
|
661
|
+
@property
|
|
662
|
+
def depth(self) -> int:
|
|
663
|
+
"""Depth."""
|
|
664
|
+
return self.__depth
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
class OntologyContext(OntologyObject):
|
|
668
|
+
"""
|
|
669
|
+
OntologyContext
|
|
670
|
+
----------------
|
|
671
|
+
Ontology context representation.
|
|
672
|
+
|
|
673
|
+
Parameters
|
|
674
|
+
----------
|
|
675
|
+
cid: str
|
|
676
|
+
Context id
|
|
677
|
+
tenant_id: str
|
|
678
|
+
Tenant id.
|
|
679
|
+
name: str
|
|
680
|
+
Name of the ontology context
|
|
681
|
+
icon: str
|
|
682
|
+
Icon or Base64 encoded
|
|
683
|
+
labels: List[Label]
|
|
684
|
+
List of labels
|
|
685
|
+
comments: List[Comment]
|
|
686
|
+
List of comments
|
|
687
|
+
context: str
|
|
688
|
+
context name
|
|
689
|
+
base_uri: str
|
|
690
|
+
Base URI
|
|
691
|
+
concepts: List[str]
|
|
692
|
+
List of classes / concepts
|
|
693
|
+
properties: List[str]
|
|
694
|
+
List of properties (data and object properties)
|
|
695
|
+
"""
|
|
696
|
+
|
|
697
|
+
def __init__(
|
|
698
|
+
self,
|
|
699
|
+
cid: str,
|
|
700
|
+
tenant_id: str,
|
|
701
|
+
name: str,
|
|
702
|
+
icon: str,
|
|
703
|
+
labels: List[OntologyLabel],
|
|
704
|
+
comments: List[Comment],
|
|
705
|
+
date_added: datetime,
|
|
706
|
+
date_modified: datetime,
|
|
707
|
+
context: str,
|
|
708
|
+
base_uri: str,
|
|
709
|
+
version: int,
|
|
710
|
+
orphaned: bool,
|
|
711
|
+
concepts: List[str],
|
|
712
|
+
properties: List[str],
|
|
713
|
+
):
|
|
714
|
+
self.__id = cid
|
|
715
|
+
self.__base_uri: str = base_uri
|
|
716
|
+
self.__version: int = version
|
|
717
|
+
self.__date_added: datetime = date_added
|
|
718
|
+
self.__date_modified: datetime = date_modified
|
|
719
|
+
self.__orphaned: bool = orphaned
|
|
720
|
+
self.__concepts: List[str] = concepts
|
|
721
|
+
self.__properties: List[str] = properties
|
|
722
|
+
super().__init__(tenant_id, name, icon, labels, comments, context)
|
|
723
|
+
|
|
724
|
+
@property
|
|
725
|
+
def id(self) -> str:
|
|
726
|
+
"""Context id."""
|
|
727
|
+
return self.__id
|
|
728
|
+
|
|
729
|
+
@property
|
|
730
|
+
def base_uri(self) -> str:
|
|
731
|
+
"""Base URI."""
|
|
732
|
+
return self.__base_uri
|
|
733
|
+
|
|
734
|
+
@property
|
|
735
|
+
def orphaned(self) -> bool:
|
|
736
|
+
"""Orphaned."""
|
|
737
|
+
return self.__orphaned
|
|
738
|
+
|
|
739
|
+
@property
|
|
740
|
+
def version(self) -> int:
|
|
741
|
+
"""Version."""
|
|
742
|
+
return self.__version
|
|
743
|
+
|
|
744
|
+
@property
|
|
745
|
+
def date_added(self) -> datetime:
|
|
746
|
+
"""Date added."""
|
|
747
|
+
return self.__date_added
|
|
748
|
+
|
|
749
|
+
@property
|
|
750
|
+
def date_modified(self) -> datetime:
|
|
751
|
+
"""Date modified."""
|
|
752
|
+
return self.__date_modified
|
|
753
|
+
|
|
754
|
+
@property
|
|
755
|
+
def concepts(self) -> List[str]:
|
|
756
|
+
"""List of concepts."""
|
|
757
|
+
return self.__concepts
|
|
758
|
+
|
|
759
|
+
@property
|
|
760
|
+
def properties(self) -> List[str]:
|
|
761
|
+
"""List of properties."""
|
|
762
|
+
return self.__properties
|
|
763
|
+
|
|
764
|
+
@classmethod
|
|
765
|
+
def from_dict(cls, context_dict: Dict[str, Any]):
|
|
766
|
+
"""
|
|
767
|
+
Create OntologyContext from dictionary.
|
|
768
|
+
|
|
769
|
+
Parameters
|
|
770
|
+
----------
|
|
771
|
+
context_dict: Dict[str, Any]
|
|
772
|
+
Dictionary containing the context data.
|
|
773
|
+
|
|
774
|
+
Returns
|
|
775
|
+
-------
|
|
776
|
+
instance: OntologyContext
|
|
777
|
+
Instance of OntologyContext object.
|
|
778
|
+
"""
|
|
779
|
+
context_data: Dict[str, Any] = context_dict["context"]
|
|
780
|
+
labels: List[OntologyLabel] = (
|
|
781
|
+
[]
|
|
782
|
+
if context_data["labels"] is None
|
|
783
|
+
else [Label(content=la[VALUE_TAG], language_code=la[LANGUAGE_TAG]) for la in context_data["labels"]]
|
|
784
|
+
)
|
|
785
|
+
comments: List[Comment] = (
|
|
786
|
+
[]
|
|
787
|
+
if context_data["comments"] is None
|
|
788
|
+
else [Comment(text=la[VALUE_TAG], language_code=la[LANGUAGE_TAG]) for la in context_data["comments"]]
|
|
789
|
+
)
|
|
790
|
+
added: datetime = datetime.fromisoformat(context_data["dateAdded"])
|
|
791
|
+
modified: datetime = datetime.fromisoformat(context_data["dateModified"])
|
|
792
|
+
return OntologyContext(
|
|
793
|
+
context_data["id"],
|
|
794
|
+
context_data["tenantId"],
|
|
795
|
+
context_data["name"],
|
|
796
|
+
context_data["icon"],
|
|
797
|
+
labels,
|
|
798
|
+
comments,
|
|
799
|
+
added,
|
|
800
|
+
modified,
|
|
801
|
+
context_data["context"],
|
|
802
|
+
context_data["baseURI"],
|
|
803
|
+
context_dict["version"],
|
|
804
|
+
context_data["orphaned"],
|
|
805
|
+
context_dict.get("concepts"),
|
|
806
|
+
context_dict.get("properties"),
|
|
807
|
+
)
|
|
808
|
+
|
|
809
|
+
def __repr__(self):
|
|
810
|
+
return f"<OntologyContext> - [id:={self.id}, iri:={self.iri}]"
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
class OntologyClass(OntologyObject):
|
|
814
|
+
"""
|
|
815
|
+
OntologyClass
|
|
816
|
+
----------------
|
|
817
|
+
Concept for ontology.
|
|
818
|
+
|
|
819
|
+
Parameters
|
|
820
|
+
----------
|
|
821
|
+
tenant_id: str
|
|
822
|
+
Tenant id for ontology
|
|
823
|
+
context: str
|
|
824
|
+
Context
|
|
825
|
+
reference: OntologyClassReference
|
|
826
|
+
Reference for ontology class
|
|
827
|
+
icon: str
|
|
828
|
+
Icon representing concept
|
|
829
|
+
labels: List[Label]
|
|
830
|
+
List of labels
|
|
831
|
+
comments: List[Comment]
|
|
832
|
+
List of comments
|
|
833
|
+
|
|
834
|
+
subclass_of: str (default: None)
|
|
835
|
+
Subclass of ontology class
|
|
836
|
+
"""
|
|
837
|
+
|
|
838
|
+
def __init__(
|
|
839
|
+
self,
|
|
840
|
+
tenant_id: str,
|
|
841
|
+
context: str,
|
|
842
|
+
reference: OntologyClassReference,
|
|
843
|
+
subclass_of: OntologyClassReference = None,
|
|
844
|
+
icon: Optional[str] = None,
|
|
845
|
+
labels: Optional[List[OntologyLabel]] = None,
|
|
846
|
+
comments: Optional[List[Comment]] = None,
|
|
847
|
+
):
|
|
848
|
+
self.__subclass_of: OntologyClassReference = subclass_of
|
|
849
|
+
self.__reference: OntologyClassReference = reference
|
|
850
|
+
super().__init__(tenant_id, reference.iri, icon, labels, comments, context)
|
|
851
|
+
|
|
852
|
+
@property
|
|
853
|
+
def subclass_of(self) -> Optional[OntologyClassReference]:
|
|
854
|
+
"""
|
|
855
|
+
Superclass of the class.
|
|
856
|
+
"""
|
|
857
|
+
return self.__subclass_of
|
|
858
|
+
|
|
859
|
+
@property
|
|
860
|
+
def reference(self) -> OntologyClassReference:
|
|
861
|
+
"""
|
|
862
|
+
Reference of ontology class.
|
|
863
|
+
"""
|
|
864
|
+
return self.__reference
|
|
865
|
+
|
|
866
|
+
def __repr__(self):
|
|
867
|
+
return f"<OntologyClass> - [reference:={self.reference}, subclass_of:={self.subclass_of}]"
|
|
868
|
+
|
|
869
|
+
@classmethod
|
|
870
|
+
def from_dict(cls, concept_dict: Dict[str, Any]):
|
|
871
|
+
"""Create OntologyClass from dictionary.
|
|
872
|
+
|
|
873
|
+
Parameters
|
|
874
|
+
----------
|
|
875
|
+
concept_dict: Dict[str, Any]
|
|
876
|
+
Dictionary containing the concept data.
|
|
877
|
+
|
|
878
|
+
Returns
|
|
879
|
+
-------
|
|
880
|
+
instance: OntologyClass
|
|
881
|
+
Instance of OntologyClass object.
|
|
882
|
+
"""
|
|
883
|
+
labels: List[OntologyLabel] = (
|
|
884
|
+
[]
|
|
885
|
+
if concept_dict[LABELS_TAG] is None
|
|
886
|
+
else [
|
|
887
|
+
OntologyLabel(content=la[VALUE_TAG], language_code=la[LANGUAGE_TAG]) for la in concept_dict[LABELS_TAG]
|
|
888
|
+
]
|
|
889
|
+
)
|
|
890
|
+
comments: List[Comment] = (
|
|
891
|
+
[]
|
|
892
|
+
if concept_dict[COMMENTS_TAG] is None
|
|
893
|
+
else [Comment(text=la[VALUE_TAG], language_code=la[LANGUAGE_TAG]) for la in concept_dict[COMMENTS_TAG]]
|
|
894
|
+
)
|
|
895
|
+
return OntologyClass(
|
|
896
|
+
tenant_id=concept_dict[TENANT_ID],
|
|
897
|
+
context=concept_dict["context"],
|
|
898
|
+
reference=OntologyClassReference.parse(concept_dict[NAME_TAG]),
|
|
899
|
+
subclass_of=(
|
|
900
|
+
OntologyClassReference.parse(concept_dict[SUB_CLASS_OF_TAG])
|
|
901
|
+
if SUB_CLASS_OF_TAG in concept_dict
|
|
902
|
+
else None
|
|
903
|
+
),
|
|
904
|
+
icon=concept_dict["icon"],
|
|
905
|
+
labels=labels,
|
|
906
|
+
comments=comments,
|
|
907
|
+
)
|
|
908
|
+
|
|
909
|
+
@classmethod
|
|
910
|
+
def new(cls) -> "OntologyClass":
|
|
911
|
+
"""
|
|
912
|
+
Create new ontology class.
|
|
913
|
+
|
|
914
|
+
Returns
|
|
915
|
+
-------
|
|
916
|
+
instance: OntologyClass
|
|
917
|
+
New ontology class.
|
|
918
|
+
"""
|
|
919
|
+
return OntologyClass("", "", THING_CLASS)
|
|
920
|
+
|
|
921
|
+
|
|
922
|
+
class OntologyProperty(OntologyObject):
|
|
923
|
+
"""
|
|
924
|
+
Ontology Property
|
|
925
|
+
-----------------
|
|
926
|
+
Property ontology object.
|
|
927
|
+
|
|
928
|
+
Parameters
|
|
929
|
+
----------
|
|
930
|
+
kind: str
|
|
931
|
+
Kind of relation
|
|
932
|
+
tenant_id: str
|
|
933
|
+
Tenant id
|
|
934
|
+
context: str
|
|
935
|
+
Context
|
|
936
|
+
name: OntologyPropertyReference
|
|
937
|
+
Name of property object
|
|
938
|
+
icon: str
|
|
939
|
+
Icon describing the property
|
|
940
|
+
property_domain: OntologyClassReference
|
|
941
|
+
Domain for the property
|
|
942
|
+
property_range: OntologyClassReference
|
|
943
|
+
Range for the property
|
|
944
|
+
labels: List[Label]
|
|
945
|
+
List of labels (localized)
|
|
946
|
+
comments: List[Comment],
|
|
947
|
+
List of comments
|
|
948
|
+
sub_property_of: str (default: = None)
|
|
949
|
+
Sub property of.
|
|
950
|
+
inverse_property_of: str (optional)
|
|
951
|
+
Inverse property
|
|
952
|
+
"""
|
|
953
|
+
|
|
954
|
+
def __init__(
|
|
955
|
+
self,
|
|
956
|
+
kind: PropertyType,
|
|
957
|
+
tenant_id: str,
|
|
958
|
+
context: str,
|
|
959
|
+
name: OntologyPropertyReference,
|
|
960
|
+
icon: str = None,
|
|
961
|
+
property_domain: Optional[List[OntologyClassReference]] = None,
|
|
962
|
+
property_range: Optional[List[Union[OntologyClassReference, DataPropertyType]]] = None,
|
|
963
|
+
labels: Optional[List[OntologyLabel]] = None,
|
|
964
|
+
comments: Optional[List[Comment]] = None,
|
|
965
|
+
sub_property_of: Optional[OntologyPropertyReference] = None,
|
|
966
|
+
inverse_property_of: Optional[OntologyPropertyReference] = None,
|
|
967
|
+
):
|
|
968
|
+
self.__kind: PropertyType = kind
|
|
969
|
+
self.__subproperty_of: OntologyPropertyReference = sub_property_of
|
|
970
|
+
self.__inverse_property_of: OntologyPropertyReference = inverse_property_of
|
|
971
|
+
self.__domains: List[OntologyClassReference] = property_domain if property_domain else []
|
|
972
|
+
self.__ranges: List[Optional[Union[OntologyClassReference, DataPropertyType]]] = (
|
|
973
|
+
property_range if property_range else []
|
|
974
|
+
)
|
|
975
|
+
self.__reference: OntologyPropertyReference = name
|
|
976
|
+
super().__init__(tenant_id, name.iri, icon, labels, comments, context)
|
|
977
|
+
|
|
978
|
+
@property
|
|
979
|
+
def is_data_property(self) -> bool:
|
|
980
|
+
"""Check if property is data property.
|
|
981
|
+
|
|
982
|
+
Returns
|
|
983
|
+
-------
|
|
984
|
+
is_data_property: bool
|
|
985
|
+
True if property is data property, False otherwise.
|
|
986
|
+
"""
|
|
987
|
+
return self.kind != PropertyType.OBJECT_PROPERTY
|
|
988
|
+
|
|
989
|
+
@property
|
|
990
|
+
def kind(self) -> PropertyType:
|
|
991
|
+
"""Kind of the property."""
|
|
992
|
+
return self.__kind
|
|
993
|
+
|
|
994
|
+
@property
|
|
995
|
+
def reference(self) -> OntologyPropertyReference:
|
|
996
|
+
"""Reference to property"""
|
|
997
|
+
return self.__reference
|
|
998
|
+
|
|
999
|
+
@property
|
|
1000
|
+
def subproperty_of(self) -> OntologyPropertyReference:
|
|
1001
|
+
"""Reference to the super property"""
|
|
1002
|
+
return self.__subproperty_of
|
|
1003
|
+
|
|
1004
|
+
@property
|
|
1005
|
+
def inverse_property_of(self) -> OntologyPropertyReference:
|
|
1006
|
+
"""Reference to the inverse property"""
|
|
1007
|
+
return self.__inverse_property_of
|
|
1008
|
+
|
|
1009
|
+
@property
|
|
1010
|
+
def domains(self) -> List[OntologyClassReference]:
|
|
1011
|
+
"""Domain of the property."""
|
|
1012
|
+
return self.__domains
|
|
1013
|
+
|
|
1014
|
+
@property
|
|
1015
|
+
def ranges(self) -> List[Union[OntologyClassReference, DataPropertyType]]:
|
|
1016
|
+
"""Ranges of the property."""
|
|
1017
|
+
return self.__ranges
|
|
1018
|
+
|
|
1019
|
+
def __repr__(self):
|
|
1020
|
+
return (
|
|
1021
|
+
f"<OntologyProperty> - [name:= {self.iri} domain:={self.domains}, range:={self.ranges}, "
|
|
1022
|
+
f"sub-property_of:={self.subproperty_of}, type:={self.kind}]"
|
|
1023
|
+
)
|
|
1024
|
+
|
|
1025
|
+
@classmethod
|
|
1026
|
+
def from_dict(cls, property_dict: Dict[str, Any]):
|
|
1027
|
+
"""
|
|
1028
|
+
Create ontology property from dictionary.
|
|
1029
|
+
Parameters
|
|
1030
|
+
----------
|
|
1031
|
+
property_dict: Dict[str, Any]
|
|
1032
|
+
Dictionary containing property information.
|
|
1033
|
+
|
|
1034
|
+
Returns
|
|
1035
|
+
-------
|
|
1036
|
+
instance: OntologyProperty
|
|
1037
|
+
Ontology property instance.
|
|
1038
|
+
"""
|
|
1039
|
+
labels: List[OntologyLabel] = (
|
|
1040
|
+
[]
|
|
1041
|
+
if property_dict[LABELS_TAG] is None
|
|
1042
|
+
else [OntologyLabel.create_from_dict(la, locale_name=LANGUAGE_TAG) for la in property_dict[LABELS_TAG]]
|
|
1043
|
+
)
|
|
1044
|
+
comments: List[Comment] = (
|
|
1045
|
+
[]
|
|
1046
|
+
if property_dict["comments"] is None
|
|
1047
|
+
else [Comment.create_from_dict(co) for co in property_dict["comments"]]
|
|
1048
|
+
)
|
|
1049
|
+
return OntologyProperty(
|
|
1050
|
+
INVERSE_PROPERTY_TYPE[property_dict["kind"]],
|
|
1051
|
+
property_dict["tenantId"],
|
|
1052
|
+
property_dict["context"],
|
|
1053
|
+
OntologyPropertyReference.parse(property_dict["name"]),
|
|
1054
|
+
property_dict["icon"],
|
|
1055
|
+
[OntologyClassReference.parse(domain) for domain in property_dict["domains"]],
|
|
1056
|
+
[OntologyClassReference.parse(domain) for domain in property_dict["ranges"]],
|
|
1057
|
+
labels,
|
|
1058
|
+
comments,
|
|
1059
|
+
(
|
|
1060
|
+
OntologyPropertyReference.parse(property_dict["subPropertyOf"])
|
|
1061
|
+
if property_dict.get("subPropertyOf") not in ["", None]
|
|
1062
|
+
else None
|
|
1063
|
+
),
|
|
1064
|
+
(
|
|
1065
|
+
OntologyPropertyReference.parse(property_dict["inverseOf"])
|
|
1066
|
+
if property_dict.get("inverseOf") not in ["", None]
|
|
1067
|
+
else None
|
|
1068
|
+
),
|
|
1069
|
+
)
|
|
1070
|
+
|
|
1071
|
+
@classmethod
|
|
1072
|
+
def new(cls, kind: PropertyType) -> "OntologyProperty":
|
|
1073
|
+
"""
|
|
1074
|
+
Create new ontology property.
|
|
1075
|
+
Parameters
|
|
1076
|
+
----------
|
|
1077
|
+
kind: PropertyType
|
|
1078
|
+
Kind of property.
|
|
1079
|
+
|
|
1080
|
+
Returns
|
|
1081
|
+
-------
|
|
1082
|
+
instance: OntologyProperty
|
|
1083
|
+
New ontology property.
|
|
1084
|
+
"""
|
|
1085
|
+
return OntologyProperty(
|
|
1086
|
+
kind, "", "", OntologyPropertyReference.parse("http://www.w3.org/2002/07/owl#topObjectProperty")
|
|
1087
|
+
)
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
class EntityProperty(abc.ABC):
|
|
1091
|
+
"""
|
|
1092
|
+
EntityProperty
|
|
1093
|
+
--------------
|
|
1094
|
+
Abstract class for the different types of properties.
|
|
1095
|
+
"""
|
|
1096
|
+
|
|
1097
|
+
|
|
1098
|
+
class DataProperty(EntityProperty):
|
|
1099
|
+
"""
|
|
1100
|
+
DataProperty
|
|
1101
|
+
------------
|
|
1102
|
+
Data property for entities.
|
|
1103
|
+
|
|
1104
|
+
Parameter
|
|
1105
|
+
---------
|
|
1106
|
+
content: Any
|
|
1107
|
+
Content
|
|
1108
|
+
literal_type: LiteralProperty
|
|
1109
|
+
OntologyPropertyReference type
|
|
1110
|
+
language_code: str
|
|
1111
|
+
Language code
|
|
1112
|
+
data_type: str
|
|
1113
|
+
Data type
|
|
1114
|
+
"""
|
|
1115
|
+
|
|
1116
|
+
def __init__(
|
|
1117
|
+
self,
|
|
1118
|
+
content: Any,
|
|
1119
|
+
property_ref: OntologyPropertyReference,
|
|
1120
|
+
language_code: LocaleCode = EN_US,
|
|
1121
|
+
data_type: DataPropertyType = None,
|
|
1122
|
+
):
|
|
1123
|
+
self.__content: Any = content
|
|
1124
|
+
self.__language_code: LocaleCode = language_code
|
|
1125
|
+
self.__type: OntologyPropertyReference = property_ref
|
|
1126
|
+
self.__data_type: Optional[DataPropertyType] = data_type
|
|
1127
|
+
|
|
1128
|
+
@property
|
|
1129
|
+
def data_property_type(self) -> OntologyPropertyReference:
|
|
1130
|
+
"""Ontology type."""
|
|
1131
|
+
return self.__type
|
|
1132
|
+
|
|
1133
|
+
@property
|
|
1134
|
+
def data_type(self) -> Optional[DataPropertyType]:
|
|
1135
|
+
"""Data type (optional)."""
|
|
1136
|
+
return self.__data_type
|
|
1137
|
+
|
|
1138
|
+
@property
|
|
1139
|
+
def value(self) -> Any:
|
|
1140
|
+
"""Content of the data property."""
|
|
1141
|
+
return self.__content
|
|
1142
|
+
|
|
1143
|
+
@property
|
|
1144
|
+
def language_code(self) -> LocaleCode:
|
|
1145
|
+
"""Language code of the content."""
|
|
1146
|
+
return self.__language_code
|
|
1147
|
+
|
|
1148
|
+
@staticmethod
|
|
1149
|
+
def create_from_dict(data_property_struct: dict):
|
|
1150
|
+
"""
|
|
1151
|
+
Create data property from dictionary.
|
|
1152
|
+
|
|
1153
|
+
Parameters
|
|
1154
|
+
----------
|
|
1155
|
+
data_property_struct: dict
|
|
1156
|
+
Dictionary containing data property information.
|
|
1157
|
+
|
|
1158
|
+
Returns
|
|
1159
|
+
-------
|
|
1160
|
+
instance: DataProperty
|
|
1161
|
+
Data property instance.
|
|
1162
|
+
"""
|
|
1163
|
+
if (
|
|
1164
|
+
CONTENT_TAG not in data_property_struct
|
|
1165
|
+
or LOCALE_TAG not in data_property_struct
|
|
1166
|
+
and DATA_PROPERTY_TAG not in data_property_struct
|
|
1167
|
+
):
|
|
1168
|
+
raise ValueError("Dict is does not contain a data_property structure.")
|
|
1169
|
+
data_property_type: str = data_property_struct[DATA_PROPERTY_TAG]
|
|
1170
|
+
data_type: DataPropertyType = DataPropertyType.STRING
|
|
1171
|
+
if DATA_TYPE_TAG in data_property_struct and data_property_struct[DATA_TYPE_TAG] is not None:
|
|
1172
|
+
if data_property_struct[DATA_TYPE_TAG] not in INVERSE_DATA_PROPERTY_TYPE_MAPPING:
|
|
1173
|
+
raise ValueError(f"DataProperty data type is not supported. Type: {data_type}")
|
|
1174
|
+
data_type = INVERSE_DATA_PROPERTY_TYPE_MAPPING[data_property_struct[DATA_TYPE_TAG]]
|
|
1175
|
+
return DataProperty(
|
|
1176
|
+
data_property_struct[CONTENT_TAG],
|
|
1177
|
+
OntologyPropertyReference.parse(data_property_type),
|
|
1178
|
+
data_property_struct[LOCALE_TAG],
|
|
1179
|
+
data_type,
|
|
1180
|
+
)
|
|
1181
|
+
|
|
1182
|
+
def __dict__(self):
|
|
1183
|
+
return {
|
|
1184
|
+
CONTENT_TAG: self.value,
|
|
1185
|
+
LOCALE_TAG: self.language_code,
|
|
1186
|
+
DATA_PROPERTY_TAG: self.data_property_type.iri,
|
|
1187
|
+
DATA_TYPE_TAG: None if self.data_type is None else self.data_type.value,
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
def __repr__(self):
|
|
1191
|
+
return f"{self.value}@{self.language_code}<{self.data_property_type.name}>"
|
|
1192
|
+
|
|
1193
|
+
@staticmethod
|
|
1194
|
+
def create_from_list(param: List[dict]) -> List["DataProperty"]:
|
|
1195
|
+
"""
|
|
1196
|
+
Create data property list from dictionary list.
|
|
1197
|
+
|
|
1198
|
+
Parameters
|
|
1199
|
+
----------
|
|
1200
|
+
param: List[dict]
|
|
1201
|
+
List of dictionaries containing data property information.
|
|
1202
|
+
|
|
1203
|
+
Returns
|
|
1204
|
+
-------
|
|
1205
|
+
instances: List[DataProperty]
|
|
1206
|
+
List of data property instances.
|
|
1207
|
+
"""
|
|
1208
|
+
return [DataProperty.create_from_dict(p) for p in param]
|
|
1209
|
+
|
|
1210
|
+
|
|
1211
|
+
class ObjectProperty(EntityProperty):
|
|
1212
|
+
"""
|
|
1213
|
+
Object Property
|
|
1214
|
+
---------------
|
|
1215
|
+
ObjectProperty for entities.
|
|
1216
|
+
|
|
1217
|
+
Parameter
|
|
1218
|
+
---------
|
|
1219
|
+
relation: OntologyPropertyReference
|
|
1220
|
+
The OntologyPropertyReference type
|
|
1221
|
+
incoming: List[str] (default:= [])
|
|
1222
|
+
Incoming relations
|
|
1223
|
+
outgoing: List[str] (default:= [])
|
|
1224
|
+
Outgoing relations
|
|
1225
|
+
"""
|
|
1226
|
+
|
|
1227
|
+
def __init__(
|
|
1228
|
+
self,
|
|
1229
|
+
relation: OntologyPropertyReference,
|
|
1230
|
+
incoming: Optional[List[Union[str, "ThingObject"]]] = None,
|
|
1231
|
+
outgoing: Optional[List[Union[str, "ThingObject"]]] = None,
|
|
1232
|
+
):
|
|
1233
|
+
self.__relation: OntologyPropertyReference = relation
|
|
1234
|
+
self.__incoming: List[Union[str, "ThingObject"]] = incoming if incoming is not None else []
|
|
1235
|
+
self.__outgoing: List[Union[str, "ThingObject"]] = outgoing if outgoing is not None else []
|
|
1236
|
+
|
|
1237
|
+
@property
|
|
1238
|
+
def relation(self) -> OntologyPropertyReference:
|
|
1239
|
+
"""Reference from the ontology."""
|
|
1240
|
+
return self.__relation
|
|
1241
|
+
|
|
1242
|
+
@property
|
|
1243
|
+
def incoming_relations(self) -> List[Union[str, "ThingObject"]]:
|
|
1244
|
+
"""Incoming relation"""
|
|
1245
|
+
return self.__incoming
|
|
1246
|
+
|
|
1247
|
+
@property
|
|
1248
|
+
def outgoing_relations(self) -> List[Union[str, "ThingObject"]]:
|
|
1249
|
+
"""Outgoing relation"""
|
|
1250
|
+
return self.__outgoing
|
|
1251
|
+
|
|
1252
|
+
@staticmethod
|
|
1253
|
+
def create_from_dict(relation_struct: Dict[str, Any]) -> Tuple[OntologyPropertyReference, "ObjectProperty"]:
|
|
1254
|
+
"""
|
|
1255
|
+
Create object property from dictionary.
|
|
1256
|
+
|
|
1257
|
+
Parameters
|
|
1258
|
+
----------
|
|
1259
|
+
relation_struct: Dict[str, Any]
|
|
1260
|
+
Dictionary containing object property information.
|
|
1261
|
+
|
|
1262
|
+
Returns
|
|
1263
|
+
-------
|
|
1264
|
+
relation_type: OntologyPropertyReference
|
|
1265
|
+
The OntologyPropertyReference type
|
|
1266
|
+
"""
|
|
1267
|
+
relation_type: OntologyPropertyReference = OntologyPropertyReference.parse(relation_struct[RELATION_TAG])
|
|
1268
|
+
incoming: List[Union[str, ThingObject]] = []
|
|
1269
|
+
|
|
1270
|
+
for incoming_relation in relation_struct[INCOMING_TAG]:
|
|
1271
|
+
if isinstance(incoming_relation, dict):
|
|
1272
|
+
incoming.append(ThingObject.from_dict(incoming_relation))
|
|
1273
|
+
elif isinstance(incoming_relation, str):
|
|
1274
|
+
incoming.append(incoming_relation)
|
|
1275
|
+
|
|
1276
|
+
outgoing: List[Union[str, ThingObject]] = []
|
|
1277
|
+
for outgoing_relation in relation_struct[OUTGOING_TAG]:
|
|
1278
|
+
if isinstance(outgoing_relation, dict):
|
|
1279
|
+
outgoing.append(ThingObject.from_dict(outgoing_relation))
|
|
1280
|
+
elif isinstance(outgoing_relation, str):
|
|
1281
|
+
outgoing.append(outgoing_relation)
|
|
1282
|
+
return relation_type, ObjectProperty(relation_type, incoming, outgoing)
|
|
1283
|
+
|
|
1284
|
+
def __dict__(self):
|
|
1285
|
+
outgoing_relations: List[str] = []
|
|
1286
|
+
incoming_relations: List[str] = []
|
|
1287
|
+
for e in self.incoming_relations:
|
|
1288
|
+
|
|
1289
|
+
if isinstance(e, ThingObject):
|
|
1290
|
+
if e.uri is not None:
|
|
1291
|
+
incoming_relations.append(e.uri)
|
|
1292
|
+
else:
|
|
1293
|
+
incoming_relations.append(e.reference_id)
|
|
1294
|
+
else:
|
|
1295
|
+
incoming_relations.append(e)
|
|
1296
|
+
for e in self.outgoing_relations:
|
|
1297
|
+
if isinstance(e, ThingObject):
|
|
1298
|
+
if e.uri is not None:
|
|
1299
|
+
outgoing_relations.append(e.uri)
|
|
1300
|
+
else:
|
|
1301
|
+
outgoing_relations.append(e.reference_id)
|
|
1302
|
+
else:
|
|
1303
|
+
outgoing_relations.append(e)
|
|
1304
|
+
return {RELATION_TAG: self.relation.iri, INCOMING_TAG: incoming_relations, OUTGOING_TAG: outgoing_relations}
|
|
1305
|
+
|
|
1306
|
+
def __repr__(self):
|
|
1307
|
+
return f"{self.relation.iri}, in:={self.incoming_relations}, out:={self.outgoing_relations}"
|
|
1308
|
+
|
|
1309
|
+
@staticmethod
|
|
1310
|
+
def create_from_list(param: List[dict]) -> Dict[OntologyPropertyReference, "ObjectProperty"]:
|
|
1311
|
+
"""
|
|
1312
|
+
Create object property list from dictionary list.
|
|
1313
|
+
Parameters
|
|
1314
|
+
----------
|
|
1315
|
+
param: List[dict]
|
|
1316
|
+
List of dictionaries containing object property information.
|
|
1317
|
+
|
|
1318
|
+
Returns
|
|
1319
|
+
-------
|
|
1320
|
+
instances: Dict[OntologyPropertyReference, ObjectProperty]
|
|
1321
|
+
Dictionary of object property instances.
|
|
1322
|
+
"""
|
|
1323
|
+
return dict([ObjectProperty.create_from_dict(p) for p in param])
|
|
1324
|
+
|
|
1325
|
+
|
|
1326
|
+
class Ontology:
|
|
1327
|
+
"""
|
|
1328
|
+
Ontology
|
|
1329
|
+
--------
|
|
1330
|
+
The ontology consists of classes and properties.
|
|
1331
|
+
"""
|
|
1332
|
+
|
|
1333
|
+
def __init__(self):
|
|
1334
|
+
self.__classes: Dict[OntologyClassReference, OntologyClass] = {}
|
|
1335
|
+
self.__data_properties: Dict[str, OntologyProperty] = {}
|
|
1336
|
+
self.__object_properties: Dict[str, OntologyProperty] = {}
|
|
1337
|
+
|
|
1338
|
+
def add_class(self, class_obj: OntologyClass):
|
|
1339
|
+
"""
|
|
1340
|
+
Adding class object.
|
|
1341
|
+
|
|
1342
|
+
Parameters
|
|
1343
|
+
----------
|
|
1344
|
+
class_obj: OntologyClass
|
|
1345
|
+
Class object
|
|
1346
|
+
"""
|
|
1347
|
+
self.__classes[class_obj.reference] = class_obj
|
|
1348
|
+
|
|
1349
|
+
def add_properties(self, prop_obj: OntologyProperty):
|
|
1350
|
+
"""
|
|
1351
|
+
Adding properties.
|
|
1352
|
+
|
|
1353
|
+
Parameters
|
|
1354
|
+
----------
|
|
1355
|
+
prop_obj: OntologyProperty
|
|
1356
|
+
"""
|
|
1357
|
+
if prop_obj.is_data_property:
|
|
1358
|
+
self.__data_properties[prop_obj.reference.iri] = prop_obj
|
|
1359
|
+
else:
|
|
1360
|
+
self.__object_properties[prop_obj.reference.iri] = prop_obj
|
|
1361
|
+
|
|
1362
|
+
@property
|
|
1363
|
+
def data_properties(self) -> List[OntologyProperty]:
|
|
1364
|
+
"""All data properties."""
|
|
1365
|
+
return list(self.__data_properties.values())
|
|
1366
|
+
|
|
1367
|
+
@property
|
|
1368
|
+
def object_properties(self) -> List[OntologyProperty]:
|
|
1369
|
+
"""All object properties."""
|
|
1370
|
+
return list(self.__object_properties.values())
|
|
1371
|
+
|
|
1372
|
+
@property
|
|
1373
|
+
def classes(self) -> List[OntologyClass]:
|
|
1374
|
+
"""All classes."""
|
|
1375
|
+
return list(self.__classes.values())
|
|
1376
|
+
|
|
1377
|
+
def __check_hierarchy__(self, clz: OntologyClassReference, domain: OntologyClassReference) -> bool:
|
|
1378
|
+
"""
|
|
1379
|
+
Check if class is in domain.
|
|
1380
|
+
Parameters
|
|
1381
|
+
----------
|
|
1382
|
+
clz: OntologyClassReference
|
|
1383
|
+
Class reference
|
|
1384
|
+
domain: OntologyClassReference
|
|
1385
|
+
Domain reference
|
|
1386
|
+
|
|
1387
|
+
Returns
|
|
1388
|
+
-------
|
|
1389
|
+
result: bool
|
|
1390
|
+
True if class is in domain.
|
|
1391
|
+
"""
|
|
1392
|
+
current_clz: Optional[OntologyClass] = self.get_class(clz)
|
|
1393
|
+
while current_clz is not None:
|
|
1394
|
+
if current_clz.reference == domain:
|
|
1395
|
+
return True
|
|
1396
|
+
current_clz = self.get_class(current_clz.subclass_of)
|
|
1397
|
+
return False
|
|
1398
|
+
|
|
1399
|
+
def get_class(self, class_reference: OntologyClassReference) -> Optional[OntologyClass]:
|
|
1400
|
+
"""
|
|
1401
|
+
Get class instance by reference.
|
|
1402
|
+
|
|
1403
|
+
Parameters
|
|
1404
|
+
----------
|
|
1405
|
+
class_reference: OntologyClassReference
|
|
1406
|
+
Class reference
|
|
1407
|
+
|
|
1408
|
+
Returns
|
|
1409
|
+
--------
|
|
1410
|
+
instance: Optional[OntologyClass]
|
|
1411
|
+
Instance of ontology class.
|
|
1412
|
+
"""
|
|
1413
|
+
return self.__classes.get(class_reference, None)
|
|
1414
|
+
|
|
1415
|
+
def get_object_properties(self, property_reference: OntologyPropertyReference) -> Optional[OntologyProperty]:
|
|
1416
|
+
"""
|
|
1417
|
+
Get object property instance by reference.
|
|
1418
|
+
|
|
1419
|
+
Parameters
|
|
1420
|
+
----------
|
|
1421
|
+
property_reference: OntologyPropertyReference
|
|
1422
|
+
Property reference
|
|
1423
|
+
|
|
1424
|
+
Returns
|
|
1425
|
+
--------
|
|
1426
|
+
instance: Optional[OntologyProperty]
|
|
1427
|
+
Instance of ontology object property.
|
|
1428
|
+
"""
|
|
1429
|
+
return self.__object_properties.get(property_reference.iri)
|
|
1430
|
+
|
|
1431
|
+
def get_data_properties(self, property_reference: OntologyPropertyReference) -> Optional[OntologyProperty]:
|
|
1432
|
+
"""
|
|
1433
|
+
Get object property instance by reference.
|
|
1434
|
+
|
|
1435
|
+
Parameters
|
|
1436
|
+
----------
|
|
1437
|
+
property_reference: OntologyPropertyReference
|
|
1438
|
+
Property reference
|
|
1439
|
+
|
|
1440
|
+
Returns
|
|
1441
|
+
--------
|
|
1442
|
+
instance: Optional[OntologyProperty]
|
|
1443
|
+
Instance of ontology object property.
|
|
1444
|
+
"""
|
|
1445
|
+
return self.__data_properties.get(property_reference.iri)
|
|
1446
|
+
|
|
1447
|
+
def data_properties_for(self, cls_reference: OntologyClassReference) -> List[OntologyPropertyReference]:
|
|
1448
|
+
"""
|
|
1449
|
+
Retrieve a list of data properties.
|
|
1450
|
+
|
|
1451
|
+
Parameters
|
|
1452
|
+
----------
|
|
1453
|
+
cls_reference: OntologyClassReference
|
|
1454
|
+
Class of the ontology
|
|
1455
|
+
|
|
1456
|
+
Returns
|
|
1457
|
+
-------
|
|
1458
|
+
data_properties: List[OntologyPropertyReference]
|
|
1459
|
+
List of data properties, where domain fit for the class of one of its super classes.
|
|
1460
|
+
"""
|
|
1461
|
+
data_properties: List[OntologyPropertyReference] = []
|
|
1462
|
+
clz: Optional[OntologyClass] = self.get_class(cls_reference)
|
|
1463
|
+
if clz is not None:
|
|
1464
|
+
for dp in self.data_properties:
|
|
1465
|
+
for domain in dp.domains:
|
|
1466
|
+
if self.__check_hierarchy__(clz.reference, domain):
|
|
1467
|
+
data_properties.append(dp.reference)
|
|
1468
|
+
return data_properties
|
|
1469
|
+
|
|
1470
|
+
def object_properties_for(self, cls_reference: OntologyClassReference) -> List[OntologyPropertyReference]:
|
|
1471
|
+
"""
|
|
1472
|
+
Retrieve a list of object properties.
|
|
1473
|
+
|
|
1474
|
+
Parameters
|
|
1475
|
+
----------
|
|
1476
|
+
cls_reference: OntologyClassReference
|
|
1477
|
+
Class of the ontology
|
|
1478
|
+
|
|
1479
|
+
Returns
|
|
1480
|
+
-------
|
|
1481
|
+
object_properties: List[OntologyPropertyReference]
|
|
1482
|
+
List of object properties, where domain fit for the class of one of its super classes.
|
|
1483
|
+
"""
|
|
1484
|
+
object_properties: List[OntologyPropertyReference] = []
|
|
1485
|
+
clz: Optional[OntologyClass] = self.get_class(cls_reference)
|
|
1486
|
+
if clz is not None:
|
|
1487
|
+
for dp in self.object_properties:
|
|
1488
|
+
for domain in dp.domains:
|
|
1489
|
+
if self.__check_hierarchy__(clz.reference, domain):
|
|
1490
|
+
object_properties.append(dp.reference)
|
|
1491
|
+
return object_properties
|
|
1492
|
+
|
|
1493
|
+
def __repr__(self):
|
|
1494
|
+
return f"<Ontology> : classes:= {self.classes}"
|
|
1495
|
+
|
|
1496
|
+
|
|
1497
|
+
class ThingObject(abc.ABC):
|
|
1498
|
+
"""
|
|
1499
|
+
ThingObject
|
|
1500
|
+
-----------
|
|
1501
|
+
Generic entity within knowledge graph.
|
|
1502
|
+
|
|
1503
|
+
Each entity is derived from this object, thus all entity shares:
|
|
1504
|
+
- **uri**: A unique resource identity to identify the entity and reference it in relations
|
|
1505
|
+
- **label**: Human understandable label
|
|
1506
|
+
- **icon**: Visual representation of the entity
|
|
1507
|
+
- **description**: Description of entity
|
|
1508
|
+
- **concept_type**: Type of the concept
|
|
1509
|
+
- **concept_type_info**: Information on the concept type
|
|
1510
|
+
- **visibility**: Visibility of the entity
|
|
1511
|
+
- **use_for_nel**: Use the entity for named entity linking
|
|
1512
|
+
|
|
1513
|
+
Parameters
|
|
1514
|
+
----------
|
|
1515
|
+
label: List[Label]
|
|
1516
|
+
List of labels
|
|
1517
|
+
icon: str (optional)
|
|
1518
|
+
Icon
|
|
1519
|
+
description: List[Description] (optional)
|
|
1520
|
+
List of descriptions
|
|
1521
|
+
concept_type: OntologyClassReference
|
|
1522
|
+
Type of the concept
|
|
1523
|
+
uri: str
|
|
1524
|
+
URI for entity. For new entities the URI is None, as the knowledge graph backend assigns this.
|
|
1525
|
+
tenant_rights: TenantAccessRight
|
|
1526
|
+
Rights for tenants
|
|
1527
|
+
owner: bool
|
|
1528
|
+
Is the logged-in user the owner of the entity
|
|
1529
|
+
use_for_nel: bool
|
|
1530
|
+
Use the entity for named entity linking
|
|
1531
|
+
use_vector_index: bool
|
|
1532
|
+
Use vector index for labels
|
|
1533
|
+
use_vector_index_document: bool
|
|
1534
|
+
Use vector index for document
|
|
1535
|
+
use_full_text_index: bool
|
|
1536
|
+
Use full text index for entity
|
|
1537
|
+
"""
|
|
1538
|
+
|
|
1539
|
+
def __init__(
|
|
1540
|
+
self,
|
|
1541
|
+
label: List[Label] = None,
|
|
1542
|
+
concept_type: OntologyClassReference = THING_CLASS,
|
|
1543
|
+
description: Optional[List[Description]] = None,
|
|
1544
|
+
uri: Optional[str] = None,
|
|
1545
|
+
icon: Optional[str] = None,
|
|
1546
|
+
tenant_rights: TenantAccessRight = TenantAccessRight(),
|
|
1547
|
+
owner: bool = True,
|
|
1548
|
+
use_for_nel: bool = True,
|
|
1549
|
+
use_vector_index: bool = False,
|
|
1550
|
+
use_vector_index_document: bool = False,
|
|
1551
|
+
use_full_text_index: bool = True,
|
|
1552
|
+
):
|
|
1553
|
+
self.__uri: str = uri
|
|
1554
|
+
self.__icon: Optional[str] = icon
|
|
1555
|
+
self.__label: List[Label] = label if label else []
|
|
1556
|
+
self.__description: List[Description] = description if description else []
|
|
1557
|
+
self.__alias: List[Label] = []
|
|
1558
|
+
self.__concept_type: OntologyClassReference = concept_type
|
|
1559
|
+
self.__data_properties: Dict[OntologyPropertyReference, List[DataProperty]] = {}
|
|
1560
|
+
self.__object_properties: Dict[OntologyPropertyReference, ObjectProperty] = {}
|
|
1561
|
+
self.__tenants_rights: TenantAccessRight = tenant_rights
|
|
1562
|
+
self.__status_flag: EntityStatus = EntityStatus.UNKNOWN
|
|
1563
|
+
self.__ontology_types: Optional[Set[str]] = None
|
|
1564
|
+
self.__owner: bool = owner
|
|
1565
|
+
self.__owner_id: Optional[str] = None
|
|
1566
|
+
self.__owner_external_user_id: Optional[str] = None
|
|
1567
|
+
self.__group_ids: List[str] = []
|
|
1568
|
+
self.__use_for_nel: bool = use_for_nel
|
|
1569
|
+
self.__use_vector_index: bool = use_vector_index
|
|
1570
|
+
self.__use_vector_index_document: bool = use_vector_index_document
|
|
1571
|
+
self.__use_full_text_index: bool = use_full_text_index
|
|
1572
|
+
self.__visibility: Optional[str] = None
|
|
1573
|
+
|
|
1574
|
+
@property
|
|
1575
|
+
def uri(self) -> str:
|
|
1576
|
+
"""Unique identifier for entity."""
|
|
1577
|
+
return self.__uri
|
|
1578
|
+
|
|
1579
|
+
@uri.setter
|
|
1580
|
+
def uri(self, uri: str):
|
|
1581
|
+
self.__uri = uri
|
|
1582
|
+
|
|
1583
|
+
@property
|
|
1584
|
+
def visibility(self) -> str:
|
|
1585
|
+
"""Visibility."""
|
|
1586
|
+
return self.__visibility
|
|
1587
|
+
|
|
1588
|
+
@visibility.setter
|
|
1589
|
+
def visibility(self, vis: str):
|
|
1590
|
+
self.__visibility = vis
|
|
1591
|
+
|
|
1592
|
+
@property
|
|
1593
|
+
def use_for_nel(self) -> bool:
|
|
1594
|
+
"""Use the entity for named entity linking."""
|
|
1595
|
+
return self.__use_for_nel
|
|
1596
|
+
|
|
1597
|
+
@use_for_nel.setter
|
|
1598
|
+
def use_for_nel(self, use_for_nel: bool):
|
|
1599
|
+
self.__use_for_nel = use_for_nel
|
|
1600
|
+
|
|
1601
|
+
@property
|
|
1602
|
+
def use_full_text_index(self) -> bool:
|
|
1603
|
+
"""Use full text index for entity."""
|
|
1604
|
+
return self.__use_full_text_index
|
|
1605
|
+
|
|
1606
|
+
@use_full_text_index.setter
|
|
1607
|
+
def use_full_text_index(self, use_full_text_index: bool):
|
|
1608
|
+
self.__use_full_text_index = use_full_text_index
|
|
1609
|
+
|
|
1610
|
+
@property
|
|
1611
|
+
def use_vector_index(self) -> bool:
|
|
1612
|
+
"""Use vector index for entity."""
|
|
1613
|
+
return self.__use_vector_index
|
|
1614
|
+
|
|
1615
|
+
@use_vector_index.setter
|
|
1616
|
+
def use_vector_index(self, use_vector_index: bool):
|
|
1617
|
+
self.__use_vector_index = use_vector_index
|
|
1618
|
+
|
|
1619
|
+
@property
|
|
1620
|
+
def use_vector_index_document(self) -> bool:
|
|
1621
|
+
"""Use vector index for document."""
|
|
1622
|
+
return self.__use_vector_index_document
|
|
1623
|
+
|
|
1624
|
+
@use_vector_index_document.setter
|
|
1625
|
+
def use_vector_index_document(self, use_vector_index_document: bool):
|
|
1626
|
+
self.__use_vector_index_document = use_vector_index_document
|
|
1627
|
+
|
|
1628
|
+
@property
|
|
1629
|
+
def owner(self) -> bool:
|
|
1630
|
+
"""Is current user the owner of the entity."""
|
|
1631
|
+
return self.__owner
|
|
1632
|
+
|
|
1633
|
+
@property
|
|
1634
|
+
def owner_id(self) -> str:
|
|
1635
|
+
"""Internal id of the owner."""
|
|
1636
|
+
return self.__owner_id
|
|
1637
|
+
|
|
1638
|
+
@owner_id.setter
|
|
1639
|
+
def owner_id(self, value: str):
|
|
1640
|
+
self.__owner_id = value
|
|
1641
|
+
|
|
1642
|
+
@property
|
|
1643
|
+
def owner_external_user_id(self) -> Optional[str]:
|
|
1644
|
+
"""External user id of the owner."""
|
|
1645
|
+
return self.__owner_external_user_id
|
|
1646
|
+
|
|
1647
|
+
@owner_external_user_id.setter
|
|
1648
|
+
def owner_external_user_id(self, value: str):
|
|
1649
|
+
self.__owner_external_user_id = value
|
|
1650
|
+
|
|
1651
|
+
@property
|
|
1652
|
+
def group_ids(self) -> List[str]:
|
|
1653
|
+
"""List of group ids."""
|
|
1654
|
+
return self.__group_ids
|
|
1655
|
+
|
|
1656
|
+
@group_ids.setter
|
|
1657
|
+
def group_ids(self, value: List[str]):
|
|
1658
|
+
self.__group_ids = value
|
|
1659
|
+
|
|
1660
|
+
@property
|
|
1661
|
+
def status_flag(self) -> EntityStatus:
|
|
1662
|
+
"""Status flag."""
|
|
1663
|
+
return self.__status_flag
|
|
1664
|
+
|
|
1665
|
+
@status_flag.setter
|
|
1666
|
+
def status_flag(self, flag: EntityStatus):
|
|
1667
|
+
self.__status_flag = flag
|
|
1668
|
+
|
|
1669
|
+
@property
|
|
1670
|
+
def label(self) -> List[Label]:
|
|
1671
|
+
"""Labels of the entity."""
|
|
1672
|
+
return self.__label
|
|
1673
|
+
|
|
1674
|
+
@label.setter
|
|
1675
|
+
def label(self, value: List[Label]):
|
|
1676
|
+
self.__label = value
|
|
1677
|
+
|
|
1678
|
+
def add_label(self, label: str, language_code: LocaleCode):
|
|
1679
|
+
"""Adding a label for entity.
|
|
1680
|
+
|
|
1681
|
+
Parameters
|
|
1682
|
+
----------
|
|
1683
|
+
label: str
|
|
1684
|
+
Label
|
|
1685
|
+
language_code: LocaleCode
|
|
1686
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., 'en_US'.
|
|
1687
|
+
"""
|
|
1688
|
+
self.__label.append(Label(label, language_code, True))
|
|
1689
|
+
|
|
1690
|
+
def update_label(self, value: str, language_code: LocaleCode):
|
|
1691
|
+
"""Update or creates a label for a specific language.
|
|
1692
|
+
|
|
1693
|
+
Parameters
|
|
1694
|
+
----------
|
|
1695
|
+
value: str
|
|
1696
|
+
Value to be set
|
|
1697
|
+
language_code: LocaleCode
|
|
1698
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., 'en_US'.
|
|
1699
|
+
"""
|
|
1700
|
+
for label in self.label:
|
|
1701
|
+
if label.language_code == language_code:
|
|
1702
|
+
label.content = value
|
|
1703
|
+
return
|
|
1704
|
+
# Label with language does not exist, so create a new label
|
|
1705
|
+
self.add_label(value, language_code)
|
|
1706
|
+
|
|
1707
|
+
def remove_label(self, language_code: LocaleCode):
|
|
1708
|
+
"""
|
|
1709
|
+
Remove label for entity if it exists for language.
|
|
1710
|
+
|
|
1711
|
+
Parameters
|
|
1712
|
+
----------
|
|
1713
|
+
language_code: LocaleCode
|
|
1714
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., 'en_US'.
|
|
1715
|
+
"""
|
|
1716
|
+
for idx, label in enumerate(self.label):
|
|
1717
|
+
if label.language_code == language_code:
|
|
1718
|
+
del self.label[idx]
|
|
1719
|
+
break
|
|
1720
|
+
|
|
1721
|
+
def remove_alias(self, label: Label):
|
|
1722
|
+
"""
|
|
1723
|
+
Remove alias for entity if it exists for language.
|
|
1724
|
+
|
|
1725
|
+
Parameters
|
|
1726
|
+
----------
|
|
1727
|
+
label: Label
|
|
1728
|
+
Alias label
|
|
1729
|
+
"""
|
|
1730
|
+
for idx, alias in enumerate(self.alias):
|
|
1731
|
+
if label.language_code == alias.language_code and label.content == alias.content:
|
|
1732
|
+
del self.alias[idx]
|
|
1733
|
+
break
|
|
1734
|
+
|
|
1735
|
+
def label_lang(self, language_code: LocaleCode) -> Optional[Label]:
|
|
1736
|
+
"""
|
|
1737
|
+
Get label for language_code code.
|
|
1738
|
+
|
|
1739
|
+
Parameters
|
|
1740
|
+
----------
|
|
1741
|
+
language_code: LocaleCode
|
|
1742
|
+
Requested language_code code
|
|
1743
|
+
Returns
|
|
1744
|
+
-------
|
|
1745
|
+
label: Optional[Label]
|
|
1746
|
+
Returns the label for a specific language code
|
|
1747
|
+
"""
|
|
1748
|
+
for label in self.label:
|
|
1749
|
+
if label.language_code == language_code:
|
|
1750
|
+
return label
|
|
1751
|
+
return None
|
|
1752
|
+
|
|
1753
|
+
def add_source_system(self, value: DataProperty):
|
|
1754
|
+
"""
|
|
1755
|
+
Adding the source system of the entity.
|
|
1756
|
+
|
|
1757
|
+
Parameters
|
|
1758
|
+
-----------
|
|
1759
|
+
value: DataProperty
|
|
1760
|
+
Adds the source system as a Data Property. **Remark:** The data property must have the property type
|
|
1761
|
+
'wacom:core#sourceSystem'.
|
|
1762
|
+
"""
|
|
1763
|
+
if value.data_property_type != SYSTEM_SOURCE_SYSTEM:
|
|
1764
|
+
raise ValueError(
|
|
1765
|
+
f"Data property {value.data_property_type.iri} not supported. " f"Expected:={SYSTEM_SOURCE_SYSTEM.iri}"
|
|
1766
|
+
)
|
|
1767
|
+
if SYSTEM_SOURCE_SYSTEM not in self.__data_properties:
|
|
1768
|
+
self.__data_properties[SYSTEM_SOURCE_SYSTEM] = []
|
|
1769
|
+
for idx in range(0, len(self.__data_properties[SYSTEM_SOURCE_SYSTEM])):
|
|
1770
|
+
if self.__data_properties[SYSTEM_SOURCE_SYSTEM][idx].language_code == value.language_code:
|
|
1771
|
+
del self.__data_properties[SYSTEM_SOURCE_SYSTEM][idx]
|
|
1772
|
+
self.__data_properties[SYSTEM_SOURCE_SYSTEM].append(value)
|
|
1773
|
+
|
|
1774
|
+
@property
|
|
1775
|
+
def source_reference_id(self) -> Optional[List[DataProperty]]:
|
|
1776
|
+
"""Reference id for to the source."""
|
|
1777
|
+
if SYSTEM_SOURCE_REFERENCE_ID in self.__data_properties:
|
|
1778
|
+
return self.__data_properties[SYSTEM_SOURCE_REFERENCE_ID]
|
|
1779
|
+
return None
|
|
1780
|
+
|
|
1781
|
+
def add_source_reference_id(self, value: DataProperty):
|
|
1782
|
+
"""
|
|
1783
|
+
Adding the reference id from the source system of the entity.
|
|
1784
|
+
|
|
1785
|
+
Parameters
|
|
1786
|
+
-----------
|
|
1787
|
+
value: DataProperty
|
|
1788
|
+
Adds the source system reference id as a Data Property.
|
|
1789
|
+
**Remark:** The data property must have the property type 'wacom:core#sourceReferenceId'.
|
|
1790
|
+
"""
|
|
1791
|
+
if value.data_property_type != SYSTEM_SOURCE_REFERENCE_ID:
|
|
1792
|
+
raise ValueError(
|
|
1793
|
+
f"Data property {value.data_property_type.iri} not supported. "
|
|
1794
|
+
f"Expected:={SYSTEM_SOURCE_REFERENCE_ID.iri}"
|
|
1795
|
+
)
|
|
1796
|
+
if SYSTEM_SOURCE_REFERENCE_ID not in self.__data_properties:
|
|
1797
|
+
self.__data_properties[SYSTEM_SOURCE_REFERENCE_ID] = []
|
|
1798
|
+
len_props: int = len(self.__data_properties[SYSTEM_SOURCE_REFERENCE_ID])
|
|
1799
|
+
idx: int = 0
|
|
1800
|
+
while idx < len_props:
|
|
1801
|
+
if self.__data_properties[SYSTEM_SOURCE_REFERENCE_ID][idx].language_code == value.language_code:
|
|
1802
|
+
del self.__data_properties[SYSTEM_SOURCE_REFERENCE_ID][idx]
|
|
1803
|
+
len_props -= 1
|
|
1804
|
+
idx += 1
|
|
1805
|
+
self.__data_properties[SYSTEM_SOURCE_REFERENCE_ID].append(value)
|
|
1806
|
+
|
|
1807
|
+
@property
|
|
1808
|
+
def reference_id(self) -> Optional[str]:
|
|
1809
|
+
"""Default reference id for the entity."""
|
|
1810
|
+
if SYSTEM_SOURCE_REFERENCE_ID in self.__data_properties:
|
|
1811
|
+
# The en_US is the default language for the source reference id
|
|
1812
|
+
for sr in self.data_properties[SYSTEM_SOURCE_REFERENCE_ID]:
|
|
1813
|
+
if sr.language_code == EN_US:
|
|
1814
|
+
return sr.value
|
|
1815
|
+
if len(self.data_properties[SYSTEM_SOURCE_REFERENCE_ID]) > 0:
|
|
1816
|
+
return self.data_properties[SYSTEM_SOURCE_REFERENCE_ID][0].value
|
|
1817
|
+
return None
|
|
1818
|
+
|
|
1819
|
+
@reference_id.setter
|
|
1820
|
+
def reference_id(self, value: str):
|
|
1821
|
+
"""
|
|
1822
|
+
Setting the default reference id for the entity.
|
|
1823
|
+
|
|
1824
|
+
Parameters
|
|
1825
|
+
----------
|
|
1826
|
+
value: str
|
|
1827
|
+
Reference id to be set
|
|
1828
|
+
"""
|
|
1829
|
+
if SYSTEM_SOURCE_REFERENCE_ID not in self.__data_properties:
|
|
1830
|
+
self.__data_properties[SYSTEM_SOURCE_REFERENCE_ID] = []
|
|
1831
|
+
self.__data_properties[SYSTEM_SOURCE_REFERENCE_ID].append(DataProperty(value, SYSTEM_SOURCE_REFERENCE_ID))
|
|
1832
|
+
|
|
1833
|
+
@property
|
|
1834
|
+
def source_system(self) -> Optional[str]:
|
|
1835
|
+
"""Default reference system for the entity."""
|
|
1836
|
+
if SYSTEM_SOURCE_REFERENCE_ID in self.__data_properties:
|
|
1837
|
+
# The en_US is the default language for the source reference system
|
|
1838
|
+
for sr in self.data_properties[SYSTEM_SOURCE_SYSTEM]:
|
|
1839
|
+
if sr.language_code == EN_US:
|
|
1840
|
+
return sr.value
|
|
1841
|
+
if len(self.data_properties[SYSTEM_SOURCE_SYSTEM]) > 0:
|
|
1842
|
+
return self.data_properties[SYSTEM_SOURCE_SYSTEM][0].value
|
|
1843
|
+
return None
|
|
1844
|
+
|
|
1845
|
+
@source_system.setter
|
|
1846
|
+
def source_system(self, value: str):
|
|
1847
|
+
"""
|
|
1848
|
+
Setting the default reference system for the entity.
|
|
1849
|
+
|
|
1850
|
+
Parameters
|
|
1851
|
+
----------
|
|
1852
|
+
value: str
|
|
1853
|
+
Reference id to be set
|
|
1854
|
+
"""
|
|
1855
|
+
if SYSTEM_SOURCE_SYSTEM not in self.__data_properties:
|
|
1856
|
+
self.__data_properties[SYSTEM_SOURCE_SYSTEM] = []
|
|
1857
|
+
self.__data_properties[SYSTEM_SOURCE_SYSTEM].append(DataProperty(value, SYSTEM_SOURCE_SYSTEM))
|
|
1858
|
+
|
|
1859
|
+
def default_source_reference_id(self, language_code: LocaleCode = EN_US) -> Optional[str]:
|
|
1860
|
+
"""
|
|
1861
|
+
Getting the source reference id for a certain language code.
|
|
1862
|
+
|
|
1863
|
+
Parameters
|
|
1864
|
+
----------
|
|
1865
|
+
language_code: LocaleCode
|
|
1866
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., 'en_US'.
|
|
1867
|
+
|
|
1868
|
+
Returns
|
|
1869
|
+
-------
|
|
1870
|
+
id: str
|
|
1871
|
+
Source reference id.
|
|
1872
|
+
"""
|
|
1873
|
+
if SYSTEM_SOURCE_REFERENCE_ID in self.__data_properties:
|
|
1874
|
+
for sr in self.data_properties[SYSTEM_SOURCE_REFERENCE_ID]:
|
|
1875
|
+
if sr.language_code == language_code:
|
|
1876
|
+
return sr.value
|
|
1877
|
+
return None
|
|
1878
|
+
|
|
1879
|
+
def default_source_system(self, language_code: LocaleCode = EN_US) -> Optional[str]:
|
|
1880
|
+
"""
|
|
1881
|
+
Getting the source system for a certain language code.
|
|
1882
|
+
|
|
1883
|
+
Parameters
|
|
1884
|
+
----------
|
|
1885
|
+
language_code: LocaleCode
|
|
1886
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., 'en_US'.
|
|
1887
|
+
|
|
1888
|
+
Returns
|
|
1889
|
+
-------
|
|
1890
|
+
id: str
|
|
1891
|
+
Source system.
|
|
1892
|
+
"""
|
|
1893
|
+
if SYSTEM_SOURCE_SYSTEM in self.__data_properties:
|
|
1894
|
+
for sr in self.data_properties[SYSTEM_SOURCE_SYSTEM]:
|
|
1895
|
+
if sr.language_code == language_code:
|
|
1896
|
+
return sr.value
|
|
1897
|
+
return None
|
|
1898
|
+
|
|
1899
|
+
@property
|
|
1900
|
+
def image(self) -> Optional[str]:
|
|
1901
|
+
"""Image depicting the entities (optional)."""
|
|
1902
|
+
return self.__icon
|
|
1903
|
+
|
|
1904
|
+
@image.setter
|
|
1905
|
+
def image(self, value: str):
|
|
1906
|
+
self.__icon = value
|
|
1907
|
+
|
|
1908
|
+
@property
|
|
1909
|
+
def description(self) -> Optional[List[Description]]:
|
|
1910
|
+
"""Description of the thing (optional)."""
|
|
1911
|
+
return self.__description
|
|
1912
|
+
|
|
1913
|
+
@description.setter
|
|
1914
|
+
def description(self, value: List[Description]):
|
|
1915
|
+
self.__description = value
|
|
1916
|
+
|
|
1917
|
+
def add_description(self, description: str, language_code: LocaleCode):
|
|
1918
|
+
"""Adding the description for entity.
|
|
1919
|
+
|
|
1920
|
+
Parameters
|
|
1921
|
+
----------
|
|
1922
|
+
description: str
|
|
1923
|
+
Description
|
|
1924
|
+
language_code: LocaleCode
|
|
1925
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., 'en_US'.
|
|
1926
|
+
"""
|
|
1927
|
+
self.__description.append(Description(description=description, language_code=language_code))
|
|
1928
|
+
|
|
1929
|
+
def update_description(self, value: str, language_code: LocaleCode):
|
|
1930
|
+
"""Update or creates a description for a specific language.
|
|
1931
|
+
|
|
1932
|
+
Parameters
|
|
1933
|
+
----------
|
|
1934
|
+
value: str
|
|
1935
|
+
Value to be set
|
|
1936
|
+
language_code: LocaleCode
|
|
1937
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., 'en_US'.
|
|
1938
|
+
"""
|
|
1939
|
+
for desc in self.description:
|
|
1940
|
+
if desc.language_code == language_code:
|
|
1941
|
+
desc.content = value
|
|
1942
|
+
return
|
|
1943
|
+
# Description with language does not exist, so create a new description
|
|
1944
|
+
self.add_description(value, language_code)
|
|
1945
|
+
|
|
1946
|
+
def description_lang(self, language_code: LocaleCode) -> Optional[Description]:
|
|
1947
|
+
"""
|
|
1948
|
+
Get description for entity.
|
|
1949
|
+
|
|
1950
|
+
Parameters
|
|
1951
|
+
----------
|
|
1952
|
+
language_code: LocaleCode
|
|
1953
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., 'en_US'.
|
|
1954
|
+
Returns
|
|
1955
|
+
-------
|
|
1956
|
+
label: LocalizedContent
|
|
1957
|
+
Returns the label for a specific language_code code
|
|
1958
|
+
"""
|
|
1959
|
+
for desc in self.description:
|
|
1960
|
+
if desc.language_code == language_code:
|
|
1961
|
+
return desc
|
|
1962
|
+
return None
|
|
1963
|
+
|
|
1964
|
+
def remove_description(self, language_code: LocaleCode):
|
|
1965
|
+
"""
|
|
1966
|
+
Remove description for entity if it exists for language.
|
|
1967
|
+
|
|
1968
|
+
Parameters
|
|
1969
|
+
----------
|
|
1970
|
+
language_code: LocaleCode
|
|
1971
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., 'en_US'.
|
|
1972
|
+
"""
|
|
1973
|
+
for index, description in enumerate(self.description):
|
|
1974
|
+
if description.language_code == language_code:
|
|
1975
|
+
del self.__description[index]
|
|
1976
|
+
break
|
|
1977
|
+
|
|
1978
|
+
@property
|
|
1979
|
+
def concept_type(self) -> OntologyClassReference:
|
|
1980
|
+
"""Concept type."""
|
|
1981
|
+
return self.__concept_type
|
|
1982
|
+
|
|
1983
|
+
@concept_type.setter
|
|
1984
|
+
def concept_type(self, value: OntologyClassReference):
|
|
1985
|
+
self.__concept_type = value
|
|
1986
|
+
|
|
1987
|
+
@property
|
|
1988
|
+
def ontology_types(self) -> Set[str]:
|
|
1989
|
+
"""Ontology types. For public entities."""
|
|
1990
|
+
return self.__ontology_types
|
|
1991
|
+
|
|
1992
|
+
@ontology_types.setter
|
|
1993
|
+
def ontology_types(self, value: Set[str]):
|
|
1994
|
+
self.__ontology_types = value
|
|
1995
|
+
|
|
1996
|
+
@property
|
|
1997
|
+
def data_properties(self) -> Dict[OntologyPropertyReference, List[DataProperty]]:
|
|
1998
|
+
"""Literals of the concept."""
|
|
1999
|
+
return self.__data_properties
|
|
2000
|
+
|
|
2001
|
+
@data_properties.setter
|
|
2002
|
+
def data_properties(self, data_properties: Dict[OntologyPropertyReference, List[DataProperty]]):
|
|
2003
|
+
"""Literals of the concept."""
|
|
2004
|
+
self.__data_properties = data_properties
|
|
2005
|
+
|
|
2006
|
+
@property
|
|
2007
|
+
def object_properties(self) -> Dict[OntologyPropertyReference, ObjectProperty]:
|
|
2008
|
+
"""Relations of the concept."""
|
|
2009
|
+
return self.__object_properties
|
|
2010
|
+
|
|
2011
|
+
@object_properties.setter
|
|
2012
|
+
def object_properties(self, relations: Dict[OntologyPropertyReference, ObjectProperty]):
|
|
2013
|
+
self.__object_properties = relations
|
|
2014
|
+
|
|
2015
|
+
def data_property_lang(
|
|
2016
|
+
self, data_property: OntologyPropertyReference, language_code: LocaleCode
|
|
2017
|
+
) -> List[DataProperty]:
|
|
2018
|
+
"""
|
|
2019
|
+
Get data property for language_code code.
|
|
2020
|
+
|
|
2021
|
+
Parameters
|
|
2022
|
+
----------
|
|
2023
|
+
data_property: OntologyPropertyReference
|
|
2024
|
+
Data property.
|
|
2025
|
+
language_code: LocaleCode
|
|
2026
|
+
Requested language_code code
|
|
2027
|
+
Returns
|
|
2028
|
+
-------
|
|
2029
|
+
data_properties: List[DataProperty]
|
|
2030
|
+
Returns a list of data properties for a specific language code
|
|
2031
|
+
"""
|
|
2032
|
+
return [d for d in self.data_properties.get(data_property, []) if d.language_code == language_code]
|
|
2033
|
+
|
|
2034
|
+
def remove_data_property(self, data_property: OntologyPropertyReference):
|
|
2035
|
+
"""Remove data property.
|
|
2036
|
+
|
|
2037
|
+
Parameters
|
|
2038
|
+
----------
|
|
2039
|
+
data_property: OntologyPropertyReference
|
|
2040
|
+
Data property to be removed.
|
|
2041
|
+
"""
|
|
2042
|
+
self.__data_properties.pop(data_property, None)
|
|
2043
|
+
|
|
2044
|
+
@property
|
|
2045
|
+
def alias(self) -> List[Label]:
|
|
2046
|
+
"""Alternative labels of the concept."""
|
|
2047
|
+
return self.__alias
|
|
2048
|
+
|
|
2049
|
+
@alias.setter
|
|
2050
|
+
def alias(self, alias: List[Label]):
|
|
2051
|
+
self.__alias = alias
|
|
2052
|
+
|
|
2053
|
+
def alias_lang(self, language_code: LocaleCode) -> List[Label]:
|
|
2054
|
+
"""
|
|
2055
|
+
Get alias for language_code code.
|
|
2056
|
+
|
|
2057
|
+
Parameters
|
|
2058
|
+
----------
|
|
2059
|
+
language_code: LocaleCode
|
|
2060
|
+
Requested language_code code
|
|
2061
|
+
Returns
|
|
2062
|
+
-------
|
|
2063
|
+
aliases: List[Label]
|
|
2064
|
+
Returns a list of aliases for a specific language code
|
|
2065
|
+
"""
|
|
2066
|
+
aliases: List[Label] = []
|
|
2067
|
+
for alias in self.alias:
|
|
2068
|
+
if alias.language_code == language_code:
|
|
2069
|
+
aliases.append(alias)
|
|
2070
|
+
return aliases
|
|
2071
|
+
|
|
2072
|
+
def update_alias(self, value: str, language_code: LocaleCode):
|
|
2073
|
+
"""Update or creates an alias for a specific language.
|
|
2074
|
+
|
|
2075
|
+
Parameters
|
|
2076
|
+
----------
|
|
2077
|
+
value: str
|
|
2078
|
+
Value to be set
|
|
2079
|
+
language_code: LocaleCode
|
|
2080
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., 'en_US'.
|
|
2081
|
+
"""
|
|
2082
|
+
for a in self.alias:
|
|
2083
|
+
if a.language_code == language_code:
|
|
2084
|
+
a.content = value
|
|
2085
|
+
return
|
|
2086
|
+
# Label with language does not exist, so create a new label
|
|
2087
|
+
self.add_alias(value, language_code=language_code)
|
|
2088
|
+
|
|
2089
|
+
def add_relation(self, prop: ObjectProperty):
|
|
2090
|
+
"""Adding a relation to the entity.
|
|
2091
|
+
|
|
2092
|
+
Parameters
|
|
2093
|
+
----------
|
|
2094
|
+
prop: ObjectProperty
|
|
2095
|
+
Object property that is added
|
|
2096
|
+
"""
|
|
2097
|
+
if prop.relation in self.object_properties:
|
|
2098
|
+
self.__object_properties[prop.relation].incoming_relations.extend(prop.incoming_relations)
|
|
2099
|
+
self.__object_properties[prop.relation].outgoing_relations.extend(prop.outgoing_relations)
|
|
2100
|
+
else:
|
|
2101
|
+
self.__object_properties[prop.relation] = prop
|
|
2102
|
+
|
|
2103
|
+
def add_data_property(self, data_property: DataProperty):
|
|
2104
|
+
"""Add data property to the entity.
|
|
2105
|
+
|
|
2106
|
+
Parameters
|
|
2107
|
+
----------
|
|
2108
|
+
data_property: DataProperty
|
|
2109
|
+
Data property that is added
|
|
2110
|
+
"""
|
|
2111
|
+
if data_property.data_property_type not in self.__data_properties:
|
|
2112
|
+
self.__data_properties[data_property.data_property_type] = []
|
|
2113
|
+
self.__data_properties[data_property.data_property_type].append(data_property)
|
|
2114
|
+
|
|
2115
|
+
def add_alias(self, alias: str, language_code: LocaleCode):
|
|
2116
|
+
"""Adding an alias for entity.
|
|
2117
|
+
|
|
2118
|
+
Parameters
|
|
2119
|
+
----------
|
|
2120
|
+
alias: str
|
|
2121
|
+
Alias
|
|
2122
|
+
language_code: LocaleCode
|
|
2123
|
+
ISO-3166 Country Codes and ISO-639 Language Codes in the format '<language_code>_<country>', e.g., 'en_US'.
|
|
2124
|
+
"""
|
|
2125
|
+
self.__alias.append(Label(alias, language_code, False))
|
|
2126
|
+
|
|
2127
|
+
@property
|
|
2128
|
+
def tenant_access_right(self) -> TenantAccessRight:
|
|
2129
|
+
"""Access rights for tenant."""
|
|
2130
|
+
return self.__tenants_rights
|
|
2131
|
+
|
|
2132
|
+
@tenant_access_right.setter
|
|
2133
|
+
def tenant_access_right(self, rights: TenantAccessRight):
|
|
2134
|
+
self.__tenants_rights = rights
|
|
2135
|
+
|
|
2136
|
+
def __dict__(self):
|
|
2137
|
+
labels: List[Dict[str, Any]] = []
|
|
2138
|
+
labels.extend([la.__dict__() for la in self.label])
|
|
2139
|
+
labels.extend([la.__dict__() for la in self.alias])
|
|
2140
|
+
dict_object: Dict[str, Any] = {
|
|
2141
|
+
URI_TAG: self.uri,
|
|
2142
|
+
IMAGE_TAG: self.image,
|
|
2143
|
+
LABELS_TAG: labels,
|
|
2144
|
+
DESCRIPTIONS_TAG: [desc.__dict__() for desc in self.description],
|
|
2145
|
+
TYPE_TAG: self.concept_type.iri,
|
|
2146
|
+
STATUS_FLAG_TAG: self.status_flag.value,
|
|
2147
|
+
DATA_PROPERTIES_TAG: {},
|
|
2148
|
+
OBJECT_PROPERTIES_TAG: {},
|
|
2149
|
+
GROUP_IDS: self.group_ids,
|
|
2150
|
+
OWNER_TAG: self.owner,
|
|
2151
|
+
OWNER_ID_TAG: self.owner_id,
|
|
2152
|
+
}
|
|
2153
|
+
for literal_type, items in self.data_properties.items():
|
|
2154
|
+
dict_object[DATA_PROPERTIES_TAG][literal_type.iri] = [i.__dict__() for i in items]
|
|
2155
|
+
for relation_type, item in self.object_properties.items():
|
|
2156
|
+
dict_object[OBJECT_PROPERTIES_TAG][relation_type.iri] = item.__dict__()
|
|
2157
|
+
return dict_object
|
|
2158
|
+
|
|
2159
|
+
def __import_format_dict__(
|
|
2160
|
+
self, group_ids: List[str] = None, external_user_id: Optional[str] = None, reference_id: Optional[str] = None
|
|
2161
|
+
) -> Dict[str, Any]:
|
|
2162
|
+
"""
|
|
2163
|
+
Export the entity to a dictionary.
|
|
2164
|
+
Parameters
|
|
2165
|
+
----------
|
|
2166
|
+
group_ids: List[str]
|
|
2167
|
+
List of group ids
|
|
2168
|
+
external_user_id: Optional[str]
|
|
2169
|
+
External user id
|
|
2170
|
+
reference_id: Optional[str]
|
|
2171
|
+
Override the reference id
|
|
2172
|
+
|
|
2173
|
+
Returns
|
|
2174
|
+
-------
|
|
2175
|
+
dict_object: Dict[str, Any]
|
|
2176
|
+
Dictionary of the entity in the import format
|
|
2177
|
+
"""
|
|
2178
|
+
labels: List[Dict[str, Any]] = []
|
|
2179
|
+
labels.extend([la.__dict__() for la in self.label])
|
|
2180
|
+
labels.extend([la.__dict__() for la in self.alias])
|
|
2181
|
+
dict_object: Dict[str, Any] = {
|
|
2182
|
+
SOURCE_REFERENCE_ID_TAG: self.source_reference_id if self.source_reference_id is None else reference_id,
|
|
2183
|
+
SOURCE_SYSTEM_TAG: self.source_system,
|
|
2184
|
+
IMAGE_TAG: self.image,
|
|
2185
|
+
LABELS_TAG: labels,
|
|
2186
|
+
DESCRIPTIONS_TAG: [desc.__dict__() for desc in self.description],
|
|
2187
|
+
TYPE_TAG: self.concept_type.iri,
|
|
2188
|
+
DATA_PROPERTIES_TAG: [],
|
|
2189
|
+
OBJECT_PROPERTIES_TAG: [],
|
|
2190
|
+
TENANT_RIGHTS_TAG: self.tenant_access_right.to_list(),
|
|
2191
|
+
GROUP_IDS: group_ids if group_ids else [],
|
|
2192
|
+
TARGETS_TAG: [],
|
|
2193
|
+
}
|
|
2194
|
+
if self.use_for_nel:
|
|
2195
|
+
dict_object[TARGETS_TAG].append(INDEXING_NEL_TARGET)
|
|
2196
|
+
if self.use_vector_index:
|
|
2197
|
+
dict_object[TARGETS_TAG].append(INDEXING_VECTOR_SEARCH_TARGET)
|
|
2198
|
+
if self.use_vector_index_document:
|
|
2199
|
+
dict_object[TARGETS_TAG].append(INDEXING_VECTOR_SEARCH_DOCUMENT_TARGET)
|
|
2200
|
+
if not self.use_full_text_index:
|
|
2201
|
+
dict_object[TARGETS_TAG].append(INDEXING_FULLTEXT_TARGET)
|
|
2202
|
+
if external_user_id:
|
|
2203
|
+
dict_object[EXTERNAL_USER_ID_TAG] = external_user_id
|
|
2204
|
+
for _, items in self.data_properties.items():
|
|
2205
|
+
dict_object[DATA_PROPERTIES_TAG].extend([i.__dict__() for i in items])
|
|
2206
|
+
for _, item in self.object_properties.items():
|
|
2207
|
+
dict_object[OBJECT_PROPERTIES_TAG].append(item.__dict__())
|
|
2208
|
+
return dict_object
|
|
2209
|
+
|
|
2210
|
+
@staticmethod
|
|
2211
|
+
def from_import_dict(entity: Dict[str, Any]) -> "ThingObject":
|
|
2212
|
+
"""Creates a ThingObject from a dict.
|
|
2213
|
+
|
|
2214
|
+
Parameters
|
|
2215
|
+
----------
|
|
2216
|
+
entity: Dict[str, Any]
|
|
2217
|
+
Dictionary that contains the data of the entity
|
|
2218
|
+
|
|
2219
|
+
Returns
|
|
2220
|
+
-------
|
|
2221
|
+
instance: ThingObject
|
|
2222
|
+
The ThingObject that is created from the dict
|
|
2223
|
+
"""
|
|
2224
|
+
labels: List[Label] = []
|
|
2225
|
+
alias: List[Label] = []
|
|
2226
|
+
descriptions: List[Description] = []
|
|
2227
|
+
main_labels: Dict[str, bool] = {}
|
|
2228
|
+
for label in entity[LABELS_TAG]:
|
|
2229
|
+
if label[LOCALE_TAG] in SUPPORTED_LOCALES:
|
|
2230
|
+
if label[IS_MAIN_TAG]:
|
|
2231
|
+
main_label: Label = Label.create_from_dict(label)
|
|
2232
|
+
main_labels[label[LOCALE_TAG]] = True
|
|
2233
|
+
labels.append(main_label)
|
|
2234
|
+
else:
|
|
2235
|
+
alias_label: Label = Label.create_from_dict(label)
|
|
2236
|
+
if alias_label.language_code not in main_labels:
|
|
2237
|
+
main_labels[alias_label.language_code] = False
|
|
2238
|
+
alias.append(alias_label)
|
|
2239
|
+
for lang_code, is_main in main_labels.items():
|
|
2240
|
+
if not is_main:
|
|
2241
|
+
la_idx: int = 0
|
|
2242
|
+
while la_idx < len(alias):
|
|
2243
|
+
# Fix things where there is no main label
|
|
2244
|
+
if alias[la_idx].language_code == lang_code:
|
|
2245
|
+
al: Label = alias[la_idx]
|
|
2246
|
+
labels.append(Label(al.content, al.language_code, main=True))
|
|
2247
|
+
del alias[la_idx]
|
|
2248
|
+
else:
|
|
2249
|
+
la_idx += 1
|
|
2250
|
+
|
|
2251
|
+
for desc in entity[DESCRIPTIONS_TAG]:
|
|
2252
|
+
if desc[LOCALE_TAG] in SUPPORTED_LOCALES:
|
|
2253
|
+
if desc[DESCRIPTION_TAG] is None:
|
|
2254
|
+
logger.warning(f"Description is None for {desc}")
|
|
2255
|
+
else:
|
|
2256
|
+
descriptions.append(Description.create_from_dict(desc))
|
|
2257
|
+
# Backwards-compatibility
|
|
2258
|
+
use_nel: bool = entity.get(USE_NEL_TAG, False)
|
|
2259
|
+
use_vector_index: bool = entity.get(USE_VECTOR_INDEX_TAG, False)
|
|
2260
|
+
use_vector_index_document: bool = entity.get(USE_VECTOR_DOCUMENT_INDEX_TAG, False)
|
|
2261
|
+
use_full_text_index: bool = entity.get(USE_FULLTEXT_TAG, True)
|
|
2262
|
+
# Vector index target
|
|
2263
|
+
if INDEXING_VECTOR_SEARCH_TARGET in entity.get(TARGETS_TAG, []):
|
|
2264
|
+
use_vector_index = True
|
|
2265
|
+
# Vector index document target
|
|
2266
|
+
if INDEXING_VECTOR_SEARCH_DOCUMENT_TARGET in entity.get(TARGETS_TAG, []):
|
|
2267
|
+
use_vector_index_document = True
|
|
2268
|
+
# Full text index target
|
|
2269
|
+
if INDEXING_FULLTEXT_TARGET in entity.get(TARGETS_TAG, []):
|
|
2270
|
+
use_full_text_index = True
|
|
2271
|
+
# Named entity linking target
|
|
2272
|
+
if INDEXING_NEL_TARGET in entity.get(TARGETS_TAG, []):
|
|
2273
|
+
use_nel = True
|
|
2274
|
+
thing: ThingObject = ThingObject(
|
|
2275
|
+
label=labels,
|
|
2276
|
+
icon=entity[IMAGE_TAG],
|
|
2277
|
+
description=descriptions,
|
|
2278
|
+
concept_type=OntologyClassReference.parse(entity[TYPE_TAG]),
|
|
2279
|
+
use_for_nel=use_nel,
|
|
2280
|
+
use_vector_index=use_vector_index,
|
|
2281
|
+
use_vector_index_document=use_vector_index_document,
|
|
2282
|
+
use_full_text_index=use_full_text_index,
|
|
2283
|
+
)
|
|
2284
|
+
if EXTERNAL_USER_ID_TAG in entity:
|
|
2285
|
+
thing.owner_external_user_id = entity[EXTERNAL_USER_ID_TAG]
|
|
2286
|
+
if DATA_PROPERTIES_TAG in entity:
|
|
2287
|
+
if isinstance(entity[DATA_PROPERTIES_TAG], dict):
|
|
2288
|
+
for data_property_type_str, data_properties in entity[DATA_PROPERTIES_TAG].items():
|
|
2289
|
+
data_property_type: OntologyPropertyReference = OntologyPropertyReference.parse(
|
|
2290
|
+
data_property_type_str
|
|
2291
|
+
)
|
|
2292
|
+
for data_property in data_properties:
|
|
2293
|
+
language_code: LocaleCode = LocaleCode(data_property[LOCALE_TAG])
|
|
2294
|
+
value: str = data_property[VALUE_TAG]
|
|
2295
|
+
thing.add_data_property(DataProperty(value, data_property_type, language_code))
|
|
2296
|
+
elif isinstance(entity[DATA_PROPERTIES_TAG], list):
|
|
2297
|
+
for data_property in entity[DATA_PROPERTIES_TAG]:
|
|
2298
|
+
language_code: LocaleCode = LocaleCode(data_property[LOCALE_TAG])
|
|
2299
|
+
value: str = data_property[VALUE_TAG]
|
|
2300
|
+
data_property_type: OntologyPropertyReference = OntologyPropertyReference.parse(
|
|
2301
|
+
data_property[DATA_PROPERTY_TAG]
|
|
2302
|
+
)
|
|
2303
|
+
thing.add_data_property(DataProperty(value, data_property_type, language_code))
|
|
2304
|
+
if OBJECT_PROPERTIES_TAG in entity:
|
|
2305
|
+
for object_property in entity[OBJECT_PROPERTIES_TAG]:
|
|
2306
|
+
_, obj = ObjectProperty.create_from_dict(object_property)
|
|
2307
|
+
thing.add_relation(obj)
|
|
2308
|
+
thing.alias = alias
|
|
2309
|
+
thing.group_ids = entity.get(GROUP_IDS, [])
|
|
2310
|
+
# Finally, retrieve rights
|
|
2311
|
+
if TENANT_RIGHTS_TAG in entity:
|
|
2312
|
+
thing.tenant_access_right = TenantAccessRight.parse(entity[TENANT_RIGHTS_TAG])
|
|
2313
|
+
return thing
|
|
2314
|
+
|
|
2315
|
+
@staticmethod
|
|
2316
|
+
def from_dict(entity: Dict[str, Any]) -> "ThingObject":
|
|
2317
|
+
"""Creates a ThingObject from a dict.
|
|
2318
|
+
|
|
2319
|
+
Parameters
|
|
2320
|
+
----------
|
|
2321
|
+
entity: Dict[str, Any]
|
|
2322
|
+
Dictionary that contains the data of the entity
|
|
2323
|
+
|
|
2324
|
+
Returns
|
|
2325
|
+
-------
|
|
2326
|
+
instance: ThingObject
|
|
2327
|
+
The ThingObject that is created from the dict
|
|
2328
|
+
"""
|
|
2329
|
+
labels: List[Label] = []
|
|
2330
|
+
alias: List[Label] = []
|
|
2331
|
+
descriptions: List[Description] = []
|
|
2332
|
+
|
|
2333
|
+
for label in entity[LABELS_TAG]:
|
|
2334
|
+
if label[LOCALE_TAG] in SUPPORTED_LOCALES:
|
|
2335
|
+
if label[IS_MAIN_TAG]:
|
|
2336
|
+
labels.append(Label.create_from_dict(label))
|
|
2337
|
+
else:
|
|
2338
|
+
alias.append(Label.create_from_dict(label))
|
|
2339
|
+
|
|
2340
|
+
for desc in entity[DESCRIPTIONS_TAG]:
|
|
2341
|
+
descriptions.append(Description.create_from_dict(desc))
|
|
2342
|
+
|
|
2343
|
+
use_nel: bool = False
|
|
2344
|
+
use_vector_index: bool = False
|
|
2345
|
+
use_vector_index_document: bool = False
|
|
2346
|
+
if TARGETS_TAG in entity:
|
|
2347
|
+
use_nel = INDEXING_NEL_TARGET in entity[TARGETS_TAG]
|
|
2348
|
+
use_vector_index = INDEXING_VECTOR_SEARCH_TARGET in entity[TARGETS_TAG]
|
|
2349
|
+
use_vector_index_document = INDEXING_VECTOR_SEARCH_DOCUMENT_TARGET in entity[TARGETS_TAG]
|
|
2350
|
+
use_fulltext_index = INDEXING_FULLTEXT_TARGET in entity[TARGETS_TAG]
|
|
2351
|
+
else:
|
|
2352
|
+
if USE_NEL_TAG in entity:
|
|
2353
|
+
use_nel = entity[USE_NEL_TAG]
|
|
2354
|
+
elif SEND_TO_NEL in entity:
|
|
2355
|
+
use_nel = entity[SEND_TO_NEL]
|
|
2356
|
+
if USE_VECTOR_INDEX_TAG in entity:
|
|
2357
|
+
use_vector_index = entity[USE_VECTOR_INDEX_TAG]
|
|
2358
|
+
elif SEND_VECTOR_INDEX_TAG in entity:
|
|
2359
|
+
use_vector_index = entity[SEND_VECTOR_INDEX_TAG]
|
|
2360
|
+
use_fulltext_index = True
|
|
2361
|
+
visibility: Optional[str] = entity.get(VISIBILITY_TAG)
|
|
2362
|
+
thing: ThingObject = ThingObject(
|
|
2363
|
+
label=labels,
|
|
2364
|
+
icon=entity[IMAGE_TAG],
|
|
2365
|
+
description=descriptions,
|
|
2366
|
+
uri=entity[URI_TAG],
|
|
2367
|
+
concept_type=OntologyClassReference.parse(entity[TYPE_TAG]),
|
|
2368
|
+
owner=entity.get(OWNER_TAG, True),
|
|
2369
|
+
use_for_nel=use_nel,
|
|
2370
|
+
use_vector_index=use_vector_index,
|
|
2371
|
+
use_vector_index_document=use_vector_index_document,
|
|
2372
|
+
use_full_text_index=use_fulltext_index,
|
|
2373
|
+
)
|
|
2374
|
+
thing.visibility = visibility
|
|
2375
|
+
thing.owner_id = entity.get(OWNER_ID_TAG)
|
|
2376
|
+
thing.group_ids = entity.get(GROUP_IDS)
|
|
2377
|
+
if DATA_PROPERTIES_TAG in entity:
|
|
2378
|
+
if isinstance(entity[DATA_PROPERTIES_TAG], dict):
|
|
2379
|
+
for data_property_type_str, data_properties in entity[DATA_PROPERTIES_TAG].items():
|
|
2380
|
+
data_property_type: OntologyPropertyReference = OntologyPropertyReference.parse(
|
|
2381
|
+
data_property_type_str
|
|
2382
|
+
)
|
|
2383
|
+
for data_property in data_properties:
|
|
2384
|
+
language_code: LocaleCode = LocaleCode(data_property[LOCALE_TAG])
|
|
2385
|
+
value: str = data_property[VALUE_TAG]
|
|
2386
|
+
thing.add_data_property(DataProperty(value, data_property_type, language_code))
|
|
2387
|
+
elif isinstance(entity[DATA_PROPERTIES_TAG], list):
|
|
2388
|
+
for data_property in entity[DATA_PROPERTIES_TAG]:
|
|
2389
|
+
language_code: LocaleCode = LocaleCode(data_property[LOCALE_TAG])
|
|
2390
|
+
value: str = data_property[VALUE_TAG]
|
|
2391
|
+
data_property_type: OntologyPropertyReference = OntologyPropertyReference.parse(
|
|
2392
|
+
data_property[DATA_PROPERTY_TAG]
|
|
2393
|
+
)
|
|
2394
|
+
thing.add_data_property(DataProperty(value, data_property_type, language_code))
|
|
2395
|
+
if OBJECT_PROPERTIES_TAG in entity:
|
|
2396
|
+
for object_property in entity[OBJECT_PROPERTIES_TAG].values():
|
|
2397
|
+
_, obj = ObjectProperty.create_from_dict(object_property)
|
|
2398
|
+
thing.add_relation(obj)
|
|
2399
|
+
thing.alias = alias
|
|
2400
|
+
# Finally, retrieve rights
|
|
2401
|
+
if TENANT_RIGHTS_TAG in entity and entity[TENANT_RIGHTS_TAG]:
|
|
2402
|
+
thing.tenant_access_right = TenantAccessRight.parse(entity[TENANT_RIGHTS_TAG])
|
|
2403
|
+
return thing
|
|
2404
|
+
|
|
2405
|
+
def __getstate__(self) -> Dict[str, Any]:
|
|
2406
|
+
return self.__dict__()
|
|
2407
|
+
|
|
2408
|
+
def __setstate__(self, state: Dict[str, Any]):
|
|
2409
|
+
self.__label: List[Label] = []
|
|
2410
|
+
self.__description: List[Description] = []
|
|
2411
|
+
self.__alias: List[Label] = []
|
|
2412
|
+
self.__data_properties: Dict[OntologyPropertyReference, List[DataProperty]] = {}
|
|
2413
|
+
self.__object_properties: Dict[OntologyPropertyReference, ObjectProperty] = {}
|
|
2414
|
+
self.__status_flag: EntityStatus = EntityStatus.UNKNOWN
|
|
2415
|
+
self.__ontology_types: Optional[Set[str]] = None
|
|
2416
|
+
self.__owner_id: Optional[str] = None
|
|
2417
|
+
self.__group_ids: List[str] = []
|
|
2418
|
+
self.__visibility: Optional[str] = None
|
|
2419
|
+
|
|
2420
|
+
for label in state[LABELS_TAG]:
|
|
2421
|
+
if label[LOCALE_TAG] in SUPPORTED_LOCALES:
|
|
2422
|
+
if label[IS_MAIN_TAG]:
|
|
2423
|
+
self.__label.append(Label.create_from_dict(label))
|
|
2424
|
+
else:
|
|
2425
|
+
self.__alias.append(Label.create_from_dict(label))
|
|
2426
|
+
|
|
2427
|
+
for desc in state[DESCRIPTIONS_TAG]:
|
|
2428
|
+
self.__description.append(Description.create_from_dict(desc))
|
|
2429
|
+
|
|
2430
|
+
use_nel: bool = state.get(USE_NEL_TAG, True)
|
|
2431
|
+
visibility: Optional[str] = state.get(VISIBILITY_TAG)
|
|
2432
|
+
self.__icon = state[IMAGE_TAG]
|
|
2433
|
+
self.__uri = state[URI_TAG]
|
|
2434
|
+
self.__concept_type = OntologyClassReference.parse(state[TYPE_TAG])
|
|
2435
|
+
self.__owner = state.get(OWNER_TAG, True)
|
|
2436
|
+
self.__use_for_nel = use_nel
|
|
2437
|
+
self.__use_vector_index = state.get(USE_VECTOR_INDEX_TAG, False)
|
|
2438
|
+
self.__use_vector_index_document = state.get(USE_VECTOR_DOCUMENT_INDEX_TAG, False)
|
|
2439
|
+
self.__use_full_text_index = state.get(USE_FULLTEXT_TAG, True)
|
|
2440
|
+
self.__visibility = visibility
|
|
2441
|
+
self.__owner_id = state.get(OWNER_ID_TAG)
|
|
2442
|
+
self.__group_ids = state.get(GROUP_IDS)
|
|
2443
|
+
if DATA_PROPERTIES_TAG in state:
|
|
2444
|
+
if isinstance(state[DATA_PROPERTIES_TAG], dict):
|
|
2445
|
+
for data_property_type_str, data_properties in state[DATA_PROPERTIES_TAG].items():
|
|
2446
|
+
data_property_type: OntologyPropertyReference = OntologyPropertyReference.parse(
|
|
2447
|
+
data_property_type_str
|
|
2448
|
+
)
|
|
2449
|
+
for data_property in data_properties:
|
|
2450
|
+
language_code: LocaleCode = LocaleCode(data_property[LOCALE_TAG])
|
|
2451
|
+
value: str = data_property[VALUE_TAG]
|
|
2452
|
+
self.add_data_property(DataProperty(value, data_property_type, language_code))
|
|
2453
|
+
elif isinstance(state[DATA_PROPERTIES_TAG], list):
|
|
2454
|
+
for data_property in state[DATA_PROPERTIES_TAG]:
|
|
2455
|
+
language_code: LocaleCode = LocaleCode(data_property[LOCALE_TAG])
|
|
2456
|
+
value: str = data_property[VALUE_TAG]
|
|
2457
|
+
data_property_type: OntologyPropertyReference = OntologyPropertyReference.parse(
|
|
2458
|
+
data_property[DATA_PROPERTY_TAG]
|
|
2459
|
+
)
|
|
2460
|
+
self.add_data_property(DataProperty(value, data_property_type, language_code))
|
|
2461
|
+
if OBJECT_PROPERTIES_TAG in state:
|
|
2462
|
+
for object_property in state[OBJECT_PROPERTIES_TAG].values():
|
|
2463
|
+
_, obj = ObjectProperty.create_from_dict(object_property)
|
|
2464
|
+
self.add_relation(obj)
|
|
2465
|
+
# Finally, retrieve rights
|
|
2466
|
+
if TENANT_RIGHTS_TAG in state:
|
|
2467
|
+
self.tenant_access_right = TenantAccessRight.parse(state[TENANT_RIGHTS_TAG])
|
|
2468
|
+
else:
|
|
2469
|
+
self.tenant_access_right = TenantAccessRight()
|
|
2470
|
+
|
|
2471
|
+
def __hash__(self):
|
|
2472
|
+
return 0
|
|
2473
|
+
|
|
2474
|
+
def __eq__(self, other: Any):
|
|
2475
|
+
# another object is equal to self, iff
|
|
2476
|
+
# it is an instance of MyClass
|
|
2477
|
+
if not isinstance(other, ThingObject):
|
|
2478
|
+
return False
|
|
2479
|
+
if self.uri != other.uri:
|
|
2480
|
+
return False
|
|
2481
|
+
other_thing: ThingObject = other
|
|
2482
|
+
# Check if the descriptions are different
|
|
2483
|
+
if len(self.description) != len(other_thing.description):
|
|
2484
|
+
return False
|
|
2485
|
+
for desc_file in self.description:
|
|
2486
|
+
kg_desc: Optional[Description] = other_thing.description_lang(desc_file.language_code)
|
|
2487
|
+
if kg_desc is None or desc_file.content != kg_desc.content:
|
|
2488
|
+
return False
|
|
2489
|
+
# Difference in vector index
|
|
2490
|
+
if self.use_vector_index != other_thing.use_vector_index:
|
|
2491
|
+
return False
|
|
2492
|
+
# Difference in NEL index
|
|
2493
|
+
if self.use_for_nel != other_thing.use_for_nel:
|
|
2494
|
+
return False
|
|
2495
|
+
if self.use_vector_index_document != other_thing.use_vector_index_document:
|
|
2496
|
+
return False
|
|
2497
|
+
|
|
2498
|
+
# Different number of labels
|
|
2499
|
+
if len(self.label) != len(other_thing.label):
|
|
2500
|
+
return False
|
|
2501
|
+
# Check if the labels are different
|
|
2502
|
+
for label_file in self.label:
|
|
2503
|
+
label_kg_lang: Optional[Label] = other_thing.label_lang(label_file.language_code)
|
|
2504
|
+
if label_kg_lang is None or label_file.content != label_kg_lang.content:
|
|
2505
|
+
return False
|
|
2506
|
+
|
|
2507
|
+
# Different number of aliases
|
|
2508
|
+
if len(self.alias) != len(other_thing.alias):
|
|
2509
|
+
return False
|
|
2510
|
+
|
|
2511
|
+
# Check if the aliases are different
|
|
2512
|
+
for alias_file in self.alias:
|
|
2513
|
+
alias_kg_lang = other_thing.alias_lang(alias_file.language_code)
|
|
2514
|
+
if alias_file.content not in [alias.content for alias in alias_kg_lang]:
|
|
2515
|
+
return False
|
|
2516
|
+
|
|
2517
|
+
# If the image is different
|
|
2518
|
+
if self.image != other_thing.image:
|
|
2519
|
+
return False
|
|
2520
|
+
|
|
2521
|
+
# If the data properties are different
|
|
2522
|
+
if len(self.data_properties) != len(other_thing.data_properties):
|
|
2523
|
+
return False
|
|
2524
|
+
|
|
2525
|
+
for prop, data_properties in self.data_properties.items():
|
|
2526
|
+
if prop not in other_thing.data_properties:
|
|
2527
|
+
return False
|
|
2528
|
+
if len(data_properties) != len(other_thing.data_properties.get(prop, [])):
|
|
2529
|
+
return False
|
|
2530
|
+
|
|
2531
|
+
for dp in data_properties:
|
|
2532
|
+
if prop not in other_thing.data_properties:
|
|
2533
|
+
return False
|
|
2534
|
+
if dp.value not in [d.value for d in other_thing.data_properties.get(prop)]:
|
|
2535
|
+
return False
|
|
2536
|
+
return True
|
|
2537
|
+
|
|
2538
|
+
def __repr__(self):
|
|
2539
|
+
return (
|
|
2540
|
+
f'<{self.concept_type.iri if self.__concept_type else "UNSET"}: uri:={self.uri}, labels:={self.label}, '
|
|
2541
|
+
f"tenant access right:={self.tenant_access_right}]>"
|
|
2542
|
+
)
|
|
2543
|
+
|
|
2544
|
+
|
|
2545
|
+
# --------------------------------------------- Inflection setting -----------------------------------------------------
|
|
2546
|
+
class InflectionSetting(abc.ABC):
|
|
2547
|
+
"""
|
|
2548
|
+
Inflection settings
|
|
2549
|
+
--------------------
|
|
2550
|
+
|
|
2551
|
+
Parameters
|
|
2552
|
+
----------
|
|
2553
|
+
concept: str
|
|
2554
|
+
Concept class
|
|
2555
|
+
inflection: str
|
|
2556
|
+
Inflection setting
|
|
2557
|
+
case_sensitive: bool
|
|
2558
|
+
Entity labels of the class treated case-sensitive
|
|
2559
|
+
"""
|
|
2560
|
+
|
|
2561
|
+
def __init__(self, concept: str, inflection: str, case_sensitive: bool):
|
|
2562
|
+
self.__concept: OntologyClassReference = OntologyClassReference.parse(concept)
|
|
2563
|
+
self.__inflection: str = inflection
|
|
2564
|
+
self.__case_sensitive: bool = case_sensitive
|
|
2565
|
+
|
|
2566
|
+
@property
|
|
2567
|
+
def concept(self) -> OntologyClassReference:
|
|
2568
|
+
"""Concept class."""
|
|
2569
|
+
return self.__concept
|
|
2570
|
+
|
|
2571
|
+
@property
|
|
2572
|
+
def inflection(self) -> str:
|
|
2573
|
+
"""Inflection setting"""
|
|
2574
|
+
return self.__inflection
|
|
2575
|
+
|
|
2576
|
+
@property
|
|
2577
|
+
def case_sensitive(self) -> bool:
|
|
2578
|
+
"""Are entity labels of the class treated case-sensitive."""
|
|
2579
|
+
return self.__case_sensitive
|
|
2580
|
+
|
|
2581
|
+
@staticmethod
|
|
2582
|
+
def from_dict(entity: Dict[str, Any]) -> "InflectionSetting":
|
|
2583
|
+
"""
|
|
2584
|
+
Create inflection setting from dictionary.
|
|
2585
|
+
Parameters
|
|
2586
|
+
----------
|
|
2587
|
+
entity: Dict[str, Any]
|
|
2588
|
+
Entity dictionary
|
|
2589
|
+
|
|
2590
|
+
Returns
|
|
2591
|
+
-------
|
|
2592
|
+
instance: InflectionSetting
|
|
2593
|
+
Inflection setting instance
|
|
2594
|
+
"""
|
|
2595
|
+
concept_class: str = ""
|
|
2596
|
+
inflection_setting: str = ""
|
|
2597
|
+
case_sensitive: bool = False
|
|
2598
|
+
if INFLECTION_CONCEPT_CLASS in entity:
|
|
2599
|
+
concept_class = entity[INFLECTION_CONCEPT_CLASS]
|
|
2600
|
+
if INFLECTION_SETTING in entity:
|
|
2601
|
+
inflection_setting = entity[INFLECTION_SETTING]
|
|
2602
|
+
if INFLECTION_CASE_SENSITIVE in entity:
|
|
2603
|
+
case_sensitive = entity[INFLECTION_CASE_SENSITIVE]
|
|
2604
|
+
return InflectionSetting(concept=concept_class, inflection=inflection_setting, case_sensitive=case_sensitive)
|
|
2605
|
+
|
|
2606
|
+
|
|
2607
|
+
# -------------------------------------------------- Encoder -----------------------------------------------------------
|
|
2608
|
+
class ThingEncoder(JSONEncoder):
|
|
2609
|
+
"""
|
|
2610
|
+
Thing encoder
|
|
2611
|
+
-------------
|
|
2612
|
+
Encoder for ThingObject, Label and Description objects.
|
|
2613
|
+
"""
|
|
2614
|
+
|
|
2615
|
+
def default(self, o: Any):
|
|
2616
|
+
if isinstance(o, (Label, Description, ThingObject)):
|
|
2617
|
+
return o.__dict__()
|
|
2618
|
+
return str(o)
|
|
2619
|
+
|
|
2620
|
+
|
|
2621
|
+
def ontology_import(rdf_content: str, tenant_id: str = "", context: str = "") -> Ontology:
|
|
2622
|
+
"""Import Ontology from RDF ontology file.
|
|
2623
|
+
|
|
2624
|
+
Parameters
|
|
2625
|
+
----------
|
|
2626
|
+
rdf_content: str
|
|
2627
|
+
Content of the RDF content file.
|
|
2628
|
+
tenant_id: str (default:= '')
|
|
2629
|
+
Tenant ID.
|
|
2630
|
+
context: str (default:= '')
|
|
2631
|
+
Context file.
|
|
2632
|
+
|
|
2633
|
+
Returns
|
|
2634
|
+
-------
|
|
2635
|
+
ontology: Ontology
|
|
2636
|
+
Instance of ontology.
|
|
2637
|
+
"""
|
|
2638
|
+
rdf_graph: Graph = Graph().parse(data=rdf_content, format="xml")
|
|
2639
|
+
ontology: Ontology = Ontology()
|
|
2640
|
+
# Parse classes
|
|
2641
|
+
for cls_iri in [s for s, p, o in list(rdf_graph.triples((None, RDF.type, OWL.Class)))]:
|
|
2642
|
+
subclass_of: Optional[OntologyClassReference] = None
|
|
2643
|
+
comments: List[Comment] = []
|
|
2644
|
+
labels: List[OntologyLabel] = []
|
|
2645
|
+
for _, _, o in list(rdf_graph.triples((cls_iri, RDFS.comment, None))):
|
|
2646
|
+
if isinstance(o, Literal):
|
|
2647
|
+
comments.append(Comment(str(o), LanguageCode(o.language)))
|
|
2648
|
+
for _, _, o in list(rdf_graph.triples((cls_iri, PREFERRED_LABEL, None))):
|
|
2649
|
+
if isinstance(o, Literal):
|
|
2650
|
+
labels.append(OntologyLabel(str(o), LanguageCode(o.language)))
|
|
2651
|
+
for _, _, o in list(rdf_graph.triples((cls_iri, RDFS.subClassOf, None))):
|
|
2652
|
+
subclass_of = OntologyClassReference.parse(str(o))
|
|
2653
|
+
ontology.add_class(
|
|
2654
|
+
OntologyClass(
|
|
2655
|
+
tenant_id=tenant_id,
|
|
2656
|
+
context=context,
|
|
2657
|
+
reference=OntologyClassReference.parse(str(cls_iri)),
|
|
2658
|
+
subclass_of=subclass_of,
|
|
2659
|
+
labels=labels,
|
|
2660
|
+
comments=comments,
|
|
2661
|
+
)
|
|
2662
|
+
)
|
|
2663
|
+
|
|
2664
|
+
# Parse data properties
|
|
2665
|
+
for data_property_iri in [s for s, p, o in list(rdf_graph.triples((None, RDF.type, OWL.DatatypeProperty)))]:
|
|
2666
|
+
subproperty_of: Optional[OntologyPropertyReference] = None
|
|
2667
|
+
range_prop: List[DataPropertyType] = []
|
|
2668
|
+
domain_prop: List[OntologyClassReference] = []
|
|
2669
|
+
comments: List[Comment] = []
|
|
2670
|
+
labels: List[OntologyLabel] = []
|
|
2671
|
+
inverse_prop: Optional[OntologyPropertyReference] = None
|
|
2672
|
+
for _, _, obj in list(rdf_graph.triples((data_property_iri, RDFS.range, None))):
|
|
2673
|
+
range_prop.append(INVERSE_DATA_PROPERTY_TYPE_MAPPING[str(obj)])
|
|
2674
|
+
for _, _, obj in list(rdf_graph.triples((data_property_iri, RDFS.domain, None))):
|
|
2675
|
+
domain_prop.append(OntologyClassReference.parse(str(obj)))
|
|
2676
|
+
for _, _, obj in list(rdf_graph.triples((data_property_iri, OWL.inverseOf, None))):
|
|
2677
|
+
inverse_prop = OntologyPropertyReference.parse(str(obj))
|
|
2678
|
+
for _, _, obj in list(rdf_graph.triples((data_property_iri, RDFS.subPropertyOf, None))):
|
|
2679
|
+
subproperty_of = OntologyPropertyReference.parse(str(obj))
|
|
2680
|
+
for _, _, o in list(rdf_graph.triples((data_property_iri, RDFS.comment, None))):
|
|
2681
|
+
if isinstance(o, Literal):
|
|
2682
|
+
comments.append(Comment(str(o), LanguageCode(o.language)))
|
|
2683
|
+
for _, _, o in list(rdf_graph.triples((data_property_iri, PREFERRED_LABEL, None))):
|
|
2684
|
+
if isinstance(o, Literal):
|
|
2685
|
+
labels.append(OntologyLabel(str(o), LanguageCode(o.language)))
|
|
2686
|
+
ontology.add_properties(
|
|
2687
|
+
OntologyProperty(
|
|
2688
|
+
kind=PropertyType.DATA_PROPERTY,
|
|
2689
|
+
tenant_id=tenant_id,
|
|
2690
|
+
context=context,
|
|
2691
|
+
name=OntologyPropertyReference.parse(str(data_property_iri)),
|
|
2692
|
+
property_range=range_prop,
|
|
2693
|
+
property_domain=domain_prop,
|
|
2694
|
+
sub_property_of=subproperty_of,
|
|
2695
|
+
inverse_property_of=inverse_prop,
|
|
2696
|
+
labels=labels,
|
|
2697
|
+
comments=comments,
|
|
2698
|
+
)
|
|
2699
|
+
)
|
|
2700
|
+
# Parse object properties
|
|
2701
|
+
for object_property_iri in [s for s, p, o in list(rdf_graph.triples((None, RDF.type, OWL.ObjectProperty)))]:
|
|
2702
|
+
subproperty_of: Optional[OntologyPropertyReference] = None
|
|
2703
|
+
obj_range_prop: List[OntologyClassReference] = []
|
|
2704
|
+
domain_prop: List[OntologyClassReference] = []
|
|
2705
|
+
inverse_prop: Optional[OntologyPropertyReference] = None
|
|
2706
|
+
comments: List[Comment] = []
|
|
2707
|
+
labels: List[OntologyLabel] = []
|
|
2708
|
+
for _, _, o_range in list(rdf_graph.triples((object_property_iri, RDFS.range, None))):
|
|
2709
|
+
obj_range_prop.append(OntologyClassReference.parse(str(o_range)))
|
|
2710
|
+
for _, _, o_domain in list(rdf_graph.triples((object_property_iri, RDFS.domain, None))):
|
|
2711
|
+
domain_prop.append(OntologyClassReference.parse(str(o_domain)))
|
|
2712
|
+
for _, _, o_inverse in list(rdf_graph.triples((object_property_iri, OWL.inverseOf, None))):
|
|
2713
|
+
inverse_prop = OntologyPropertyReference.parse(str(o_inverse))
|
|
2714
|
+
for _, _, o_sub in list(rdf_graph.triples((object_property_iri, RDFS.subPropertyOf, None))):
|
|
2715
|
+
subproperty_of = OntologyPropertyReference.parse(str(o_sub))
|
|
2716
|
+
for _, _, o in list(rdf_graph.triples((object_property_iri, RDFS.comment, None))):
|
|
2717
|
+
if isinstance(o, Literal):
|
|
2718
|
+
comments.append(Comment(str(o), LanguageCode(o.language)))
|
|
2719
|
+
for _, _, o in list(rdf_graph.triples((object_property_iri, PREFERRED_LABEL, None))):
|
|
2720
|
+
if isinstance(o, Literal):
|
|
2721
|
+
labels.append(OntologyLabel(str(o), LanguageCode(o.language)))
|
|
2722
|
+
ontology.add_properties(
|
|
2723
|
+
OntologyProperty(
|
|
2724
|
+
kind=PropertyType.OBJECT_PROPERTY,
|
|
2725
|
+
tenant_id=tenant_id,
|
|
2726
|
+
context=context,
|
|
2727
|
+
name=OntologyPropertyReference.parse(str(object_property_iri)),
|
|
2728
|
+
property_range=obj_range_prop,
|
|
2729
|
+
property_domain=domain_prop,
|
|
2730
|
+
sub_property_of=subproperty_of,
|
|
2731
|
+
inverse_property_of=inverse_prop,
|
|
2732
|
+
)
|
|
2733
|
+
)
|
|
2734
|
+
return ontology
|