rdf-construct 0.3.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.
- rdf_construct/__init__.py +12 -0
- rdf_construct/__main__.py +0 -0
- rdf_construct/cli.py +3429 -0
- rdf_construct/core/__init__.py +33 -0
- rdf_construct/core/config.py +116 -0
- rdf_construct/core/ordering.py +219 -0
- rdf_construct/core/predicate_order.py +212 -0
- rdf_construct/core/profile.py +157 -0
- rdf_construct/core/selector.py +64 -0
- rdf_construct/core/serialiser.py +232 -0
- rdf_construct/core/utils.py +89 -0
- rdf_construct/cq/__init__.py +77 -0
- rdf_construct/cq/expectations.py +365 -0
- rdf_construct/cq/formatters/__init__.py +45 -0
- rdf_construct/cq/formatters/json.py +104 -0
- rdf_construct/cq/formatters/junit.py +104 -0
- rdf_construct/cq/formatters/text.py +146 -0
- rdf_construct/cq/loader.py +300 -0
- rdf_construct/cq/runner.py +321 -0
- rdf_construct/diff/__init__.py +59 -0
- rdf_construct/diff/change_types.py +214 -0
- rdf_construct/diff/comparator.py +338 -0
- rdf_construct/diff/filters.py +133 -0
- rdf_construct/diff/formatters/__init__.py +71 -0
- rdf_construct/diff/formatters/json.py +192 -0
- rdf_construct/diff/formatters/markdown.py +210 -0
- rdf_construct/diff/formatters/text.py +195 -0
- rdf_construct/docs/__init__.py +60 -0
- rdf_construct/docs/config.py +238 -0
- rdf_construct/docs/extractors.py +603 -0
- rdf_construct/docs/generator.py +360 -0
- rdf_construct/docs/renderers/__init__.py +7 -0
- rdf_construct/docs/renderers/html.py +803 -0
- rdf_construct/docs/renderers/json.py +390 -0
- rdf_construct/docs/renderers/markdown.py +628 -0
- rdf_construct/docs/search.py +278 -0
- rdf_construct/docs/templates/html/base.html.jinja +44 -0
- rdf_construct/docs/templates/html/class.html.jinja +152 -0
- rdf_construct/docs/templates/html/hierarchy.html.jinja +28 -0
- rdf_construct/docs/templates/html/index.html.jinja +110 -0
- rdf_construct/docs/templates/html/instance.html.jinja +90 -0
- rdf_construct/docs/templates/html/namespaces.html.jinja +37 -0
- rdf_construct/docs/templates/html/property.html.jinja +124 -0
- rdf_construct/docs/templates/html/single_page.html.jinja +169 -0
- rdf_construct/lint/__init__.py +75 -0
- rdf_construct/lint/config.py +214 -0
- rdf_construct/lint/engine.py +396 -0
- rdf_construct/lint/formatters.py +327 -0
- rdf_construct/lint/rules.py +692 -0
- rdf_construct/localise/__init__.py +114 -0
- rdf_construct/localise/config.py +508 -0
- rdf_construct/localise/extractor.py +427 -0
- rdf_construct/localise/formatters/__init__.py +36 -0
- rdf_construct/localise/formatters/markdown.py +229 -0
- rdf_construct/localise/formatters/text.py +224 -0
- rdf_construct/localise/merger.py +346 -0
- rdf_construct/localise/reporter.py +356 -0
- rdf_construct/main.py +6 -0
- rdf_construct/merge/__init__.py +165 -0
- rdf_construct/merge/config.py +354 -0
- rdf_construct/merge/conflicts.py +281 -0
- rdf_construct/merge/formatters.py +426 -0
- rdf_construct/merge/merger.py +425 -0
- rdf_construct/merge/migrator.py +339 -0
- rdf_construct/merge/rules.py +377 -0
- rdf_construct/merge/splitter.py +1102 -0
- rdf_construct/puml2rdf/__init__.py +103 -0
- rdf_construct/puml2rdf/config.py +230 -0
- rdf_construct/puml2rdf/converter.py +420 -0
- rdf_construct/puml2rdf/merger.py +200 -0
- rdf_construct/puml2rdf/model.py +202 -0
- rdf_construct/puml2rdf/parser.py +565 -0
- rdf_construct/puml2rdf/validators.py +451 -0
- rdf_construct/refactor/__init__.py +72 -0
- rdf_construct/refactor/config.py +362 -0
- rdf_construct/refactor/deprecator.py +328 -0
- rdf_construct/refactor/formatters/__init__.py +8 -0
- rdf_construct/refactor/formatters/text.py +311 -0
- rdf_construct/refactor/renamer.py +294 -0
- rdf_construct/shacl/__init__.py +56 -0
- rdf_construct/shacl/config.py +166 -0
- rdf_construct/shacl/converters.py +520 -0
- rdf_construct/shacl/generator.py +364 -0
- rdf_construct/shacl/namespaces.py +93 -0
- rdf_construct/stats/__init__.py +29 -0
- rdf_construct/stats/collector.py +178 -0
- rdf_construct/stats/comparator.py +298 -0
- rdf_construct/stats/formatters/__init__.py +83 -0
- rdf_construct/stats/formatters/json.py +38 -0
- rdf_construct/stats/formatters/markdown.py +153 -0
- rdf_construct/stats/formatters/text.py +186 -0
- rdf_construct/stats/metrics/__init__.py +26 -0
- rdf_construct/stats/metrics/basic.py +147 -0
- rdf_construct/stats/metrics/complexity.py +137 -0
- rdf_construct/stats/metrics/connectivity.py +130 -0
- rdf_construct/stats/metrics/documentation.py +128 -0
- rdf_construct/stats/metrics/hierarchy.py +207 -0
- rdf_construct/stats/metrics/properties.py +88 -0
- rdf_construct/uml/__init__.py +22 -0
- rdf_construct/uml/context.py +194 -0
- rdf_construct/uml/mapper.py +371 -0
- rdf_construct/uml/odm_renderer.py +789 -0
- rdf_construct/uml/renderer.py +684 -0
- rdf_construct/uml/uml_layout.py +393 -0
- rdf_construct/uml/uml_style.py +613 -0
- rdf_construct-0.3.0.dist-info/METADATA +496 -0
- rdf_construct-0.3.0.dist-info/RECORD +110 -0
- rdf_construct-0.3.0.dist-info/WHEEL +4 -0
- rdf_construct-0.3.0.dist-info/entry_points.txt +3 -0
- rdf_construct-0.3.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
"""Map RDF ontology entities to UML diagram elements.
|
|
2
|
+
|
|
3
|
+
This module handles the selection and filtering of classes, properties,
|
|
4
|
+
and instances from an RDF graph based on UML context specifications.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
from rdflib import Graph, URIRef, RDF, RDFS
|
|
10
|
+
from rdflib.namespace import OWL
|
|
11
|
+
|
|
12
|
+
from ..core.utils import expand_curie, qname_sort_key
|
|
13
|
+
from ..core.selector import select_subjects
|
|
14
|
+
from .context import UMLContext
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_descendants(
|
|
18
|
+
graph: Graph, root: URIRef, max_depth: Optional[int] = None
|
|
19
|
+
) -> set[URIRef]:
|
|
20
|
+
"""Get all descendant classes of a root class.
|
|
21
|
+
|
|
22
|
+
Traverses rdfs:subClassOf relationships to find all classes that
|
|
23
|
+
inherit from the root, optionally limiting depth.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
graph: RDF graph to traverse
|
|
27
|
+
root: Root class URI
|
|
28
|
+
max_depth: Maximum depth to traverse (None = unlimited)
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Set of URIRefs including root and all descendants
|
|
32
|
+
"""
|
|
33
|
+
descendants = {root}
|
|
34
|
+
current_level = {root}
|
|
35
|
+
depth = 0
|
|
36
|
+
|
|
37
|
+
while current_level:
|
|
38
|
+
if max_depth is not None and depth >= max_depth:
|
|
39
|
+
break
|
|
40
|
+
|
|
41
|
+
next_level = set()
|
|
42
|
+
for cls in current_level:
|
|
43
|
+
# Find direct subclasses
|
|
44
|
+
for subclass in graph.subjects(RDFS.subClassOf, cls):
|
|
45
|
+
if isinstance(subclass, URIRef) and subclass not in descendants:
|
|
46
|
+
descendants.add(subclass)
|
|
47
|
+
next_level.add(subclass)
|
|
48
|
+
|
|
49
|
+
current_level = next_level
|
|
50
|
+
depth += 1
|
|
51
|
+
|
|
52
|
+
return descendants
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def select_classes(
|
|
56
|
+
graph: Graph, context: UMLContext, selectors: dict[str, str]
|
|
57
|
+
) -> set[URIRef]:
|
|
58
|
+
"""Select classes for diagram based on context configuration.
|
|
59
|
+
|
|
60
|
+
Supports three selection modes:
|
|
61
|
+
1. root_classes: Start from specific roots and optionally include descendants
|
|
62
|
+
2. focus_classes: Explicit list of classes to include
|
|
63
|
+
3. selector: Use selector key (e.g., "classes") to select all matching
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
graph: RDF graph to select from
|
|
67
|
+
context: UML context specifying selection criteria
|
|
68
|
+
selectors: Selector definitions from config
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Set of URIRefs for selected classes
|
|
72
|
+
"""
|
|
73
|
+
selected: set[URIRef] = set()
|
|
74
|
+
|
|
75
|
+
# Strategy 1: Root classes with optional descendants
|
|
76
|
+
if context.root_classes:
|
|
77
|
+
for curie in context.root_classes:
|
|
78
|
+
root = expand_curie(graph, curie)
|
|
79
|
+
if root is None:
|
|
80
|
+
continue
|
|
81
|
+
|
|
82
|
+
if context.include_descendants:
|
|
83
|
+
descendants = get_descendants(graph, root, context.max_depth)
|
|
84
|
+
selected.update(descendants)
|
|
85
|
+
else:
|
|
86
|
+
selected.add(root)
|
|
87
|
+
|
|
88
|
+
# Strategy 2: Explicit focus classes
|
|
89
|
+
elif context.focus_classes:
|
|
90
|
+
for curie in context.focus_classes:
|
|
91
|
+
cls = expand_curie(graph, curie)
|
|
92
|
+
if cls is not None:
|
|
93
|
+
selected.add(cls)
|
|
94
|
+
|
|
95
|
+
# Optionally include descendants
|
|
96
|
+
if context.include_descendants:
|
|
97
|
+
descendants = get_descendants(graph, cls, context.max_depth)
|
|
98
|
+
selected.update(descendants)
|
|
99
|
+
|
|
100
|
+
# Strategy 3: Use selector (e.g., all classes)
|
|
101
|
+
elif context.selector:
|
|
102
|
+
selected = select_subjects(graph, context.selector, selectors)
|
|
103
|
+
|
|
104
|
+
return selected
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def select_properties(
|
|
108
|
+
graph: Graph, context: UMLContext, selected_classes: set[URIRef]
|
|
109
|
+
) -> dict[str, set[URIRef]]:
|
|
110
|
+
"""Select properties for diagram based on context and selected classes.
|
|
111
|
+
|
|
112
|
+
Returns properties categorized by type (object/datatype/annotation).
|
|
113
|
+
Different modes control which properties are included:
|
|
114
|
+
- 'domain_based': Properties whose domain is in selected classes
|
|
115
|
+
- 'connected': Properties connecting selected classes
|
|
116
|
+
- 'explicit': Only explicitly listed properties
|
|
117
|
+
- 'all': All properties in the graph
|
|
118
|
+
- 'none': No properties
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
graph: RDF graph to select from
|
|
122
|
+
context: UML context specifying property criteria
|
|
123
|
+
selected_classes: Set of classes already selected for diagram
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
Dictionary with keys 'object', 'datatype', 'annotation' mapping to
|
|
127
|
+
sets of URIRefs for each property type
|
|
128
|
+
"""
|
|
129
|
+
properties = {
|
|
130
|
+
"object": set(),
|
|
131
|
+
"datatype": set(),
|
|
132
|
+
"annotation": set(),
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
# Get all properties by type
|
|
136
|
+
all_obj_props = {s for s in graph.subjects(RDF.type, OWL.ObjectProperty)}
|
|
137
|
+
all_data_props = {s for s in graph.subjects(RDF.type, OWL.DatatypeProperty)}
|
|
138
|
+
all_ann_props = {s for s in graph.subjects(RDF.type, OWL.AnnotationProperty)}
|
|
139
|
+
|
|
140
|
+
mode = context.property_mode
|
|
141
|
+
|
|
142
|
+
if mode == "none":
|
|
143
|
+
return properties
|
|
144
|
+
|
|
145
|
+
elif mode == "all":
|
|
146
|
+
properties["object"] = all_obj_props
|
|
147
|
+
properties["datatype"] = all_data_props
|
|
148
|
+
properties["annotation"] = all_ann_props
|
|
149
|
+
|
|
150
|
+
elif mode == "explicit":
|
|
151
|
+
# Only include explicitly listed properties
|
|
152
|
+
for curie in context.property_include:
|
|
153
|
+
prop = expand_curie(graph, curie)
|
|
154
|
+
if prop is None:
|
|
155
|
+
continue
|
|
156
|
+
|
|
157
|
+
if prop in all_obj_props:
|
|
158
|
+
properties["object"].add(prop)
|
|
159
|
+
elif prop in all_data_props:
|
|
160
|
+
properties["datatype"].add(prop)
|
|
161
|
+
elif prop in all_ann_props:
|
|
162
|
+
properties["annotation"].add(prop)
|
|
163
|
+
|
|
164
|
+
elif mode == "domain_based":
|
|
165
|
+
# Include properties whose domain is in selected classes
|
|
166
|
+
for prop in all_obj_props | all_data_props | all_ann_props:
|
|
167
|
+
domains = set(graph.objects(prop, RDFS.domain))
|
|
168
|
+
|
|
169
|
+
# Check if any domain is in selected classes
|
|
170
|
+
if domains & selected_classes:
|
|
171
|
+
if prop in all_obj_props:
|
|
172
|
+
properties["object"].add(prop)
|
|
173
|
+
elif prop in all_data_props:
|
|
174
|
+
properties["datatype"].add(prop)
|
|
175
|
+
elif prop in all_ann_props:
|
|
176
|
+
properties["annotation"].add(prop)
|
|
177
|
+
|
|
178
|
+
elif mode == "connected":
|
|
179
|
+
# Include object properties that connect selected classes
|
|
180
|
+
for prop in all_obj_props:
|
|
181
|
+
domains = set(graph.objects(prop, RDFS.domain))
|
|
182
|
+
ranges = set(graph.objects(prop, RDFS.range))
|
|
183
|
+
|
|
184
|
+
# Both domain and range must be in selected classes
|
|
185
|
+
if (domains & selected_classes) and (ranges & selected_classes):
|
|
186
|
+
properties["object"].add(prop)
|
|
187
|
+
|
|
188
|
+
# For datatype props, just check domain
|
|
189
|
+
for prop in all_data_props:
|
|
190
|
+
domains = set(graph.objects(prop, RDFS.domain))
|
|
191
|
+
if domains & selected_classes:
|
|
192
|
+
properties["datatype"].add(prop)
|
|
193
|
+
|
|
194
|
+
# Apply exclusions
|
|
195
|
+
for curie in context.property_exclude:
|
|
196
|
+
prop = expand_curie(graph, curie)
|
|
197
|
+
if prop:
|
|
198
|
+
properties["object"].discard(prop)
|
|
199
|
+
properties["datatype"].discard(prop)
|
|
200
|
+
properties["annotation"].discard(prop)
|
|
201
|
+
|
|
202
|
+
return properties
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def select_instances(
|
|
206
|
+
graph: Graph, selected_classes: set[URIRef]
|
|
207
|
+
) -> set[URIRef]:
|
|
208
|
+
"""Select instances of the selected classes.
|
|
209
|
+
|
|
210
|
+
Args:
|
|
211
|
+
graph: RDF graph to select from
|
|
212
|
+
selected_classes: Classes whose instances to select
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
Set of URIRefs for individuals that are instances of selected classes
|
|
216
|
+
"""
|
|
217
|
+
instances = set()
|
|
218
|
+
|
|
219
|
+
for cls in selected_classes:
|
|
220
|
+
# Find all instances of this class
|
|
221
|
+
for instance in graph.subjects(RDF.type, cls):
|
|
222
|
+
if isinstance(instance, URIRef):
|
|
223
|
+
instances.add(instance)
|
|
224
|
+
|
|
225
|
+
return instances
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def collect_explicit_entities(
|
|
229
|
+
graph: Graph, context: UMLContext
|
|
230
|
+
) -> dict[str, set[URIRef]]:
|
|
231
|
+
"""Collect entities explicitly specified in context.
|
|
232
|
+
|
|
233
|
+
In explicit mode, all entities are directly listed in the configuration
|
|
234
|
+
rather than selected via strategies. This provides complete control over
|
|
235
|
+
diagram contents.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
graph: RDF graph to validate entities against
|
|
239
|
+
context: UML context with explicit entity lists
|
|
240
|
+
|
|
241
|
+
Returns:
|
|
242
|
+
Dictionary with keys:
|
|
243
|
+
- 'classes': Explicitly specified class URIRefs
|
|
244
|
+
- 'object_properties': Explicitly specified object property URIRefs
|
|
245
|
+
- 'datatype_properties': Explicitly specified datatype property URIRefs
|
|
246
|
+
- 'annotation_properties': Explicitly specified annotation property URIRefs
|
|
247
|
+
- 'instances': Explicitly specified instance URIRefs
|
|
248
|
+
|
|
249
|
+
Raises:
|
|
250
|
+
ValueError: If a CURIE cannot be expanded or entity doesn't exist
|
|
251
|
+
"""
|
|
252
|
+
entities = {
|
|
253
|
+
"classes": set(),
|
|
254
|
+
"object_properties": set(),
|
|
255
|
+
"datatype_properties": set(),
|
|
256
|
+
"annotation_properties": set(),
|
|
257
|
+
"instances": set(),
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
# Get all properties by type for validation
|
|
261
|
+
all_obj_props = {s for s in graph.subjects(RDF.type, OWL.ObjectProperty)}
|
|
262
|
+
all_data_props = {s for s in graph.subjects(RDF.type, OWL.DatatypeProperty)}
|
|
263
|
+
all_ann_props = {s for s in graph.subjects(RDF.type, OWL.AnnotationProperty)}
|
|
264
|
+
|
|
265
|
+
# Expand and validate classes
|
|
266
|
+
for curie in context.explicit_classes:
|
|
267
|
+
uri = expand_curie(graph, curie)
|
|
268
|
+
if uri is None:
|
|
269
|
+
raise ValueError(f"Cannot expand CURIE: {curie}")
|
|
270
|
+
|
|
271
|
+
# Validate it's actually a class
|
|
272
|
+
is_class = (
|
|
273
|
+
(uri, RDF.type, OWL.Class) in graph or
|
|
274
|
+
(uri, RDF.type, RDFS.Class) in graph
|
|
275
|
+
)
|
|
276
|
+
if not is_class:
|
|
277
|
+
# Warning but don't fail - might be a valid use case
|
|
278
|
+
pass
|
|
279
|
+
|
|
280
|
+
entities["classes"].add(uri)
|
|
281
|
+
|
|
282
|
+
# Expand and validate object properties
|
|
283
|
+
for curie in context.explicit_object_properties:
|
|
284
|
+
uri = expand_curie(graph, curie)
|
|
285
|
+
if uri is None:
|
|
286
|
+
raise ValueError(f"Cannot expand CURIE: {curie}")
|
|
287
|
+
|
|
288
|
+
if uri not in all_obj_props:
|
|
289
|
+
# Warning but don't fail
|
|
290
|
+
pass
|
|
291
|
+
|
|
292
|
+
entities["object_properties"].add(uri)
|
|
293
|
+
|
|
294
|
+
# Expand and validate datatype properties
|
|
295
|
+
for curie in context.explicit_datatype_properties:
|
|
296
|
+
uri = expand_curie(graph, curie)
|
|
297
|
+
if uri is None:
|
|
298
|
+
raise ValueError(f"Cannot expand CURIE: {curie}")
|
|
299
|
+
|
|
300
|
+
if uri not in all_data_props:
|
|
301
|
+
pass
|
|
302
|
+
|
|
303
|
+
entities["datatype_properties"].add(uri)
|
|
304
|
+
|
|
305
|
+
# Expand and validate annotation properties
|
|
306
|
+
for curie in context.explicit_annotation_properties:
|
|
307
|
+
uri = expand_curie(graph, curie)
|
|
308
|
+
if uri is None:
|
|
309
|
+
raise ValueError(f"Cannot expand CURIE: {curie}")
|
|
310
|
+
|
|
311
|
+
if uri not in all_ann_props:
|
|
312
|
+
pass
|
|
313
|
+
|
|
314
|
+
entities["annotation_properties"].add(uri)
|
|
315
|
+
|
|
316
|
+
# Expand instances
|
|
317
|
+
for curie in context.explicit_instances:
|
|
318
|
+
uri = expand_curie(graph, curie)
|
|
319
|
+
if uri is None:
|
|
320
|
+
raise ValueError(f"Cannot expand CURIE: {curie}")
|
|
321
|
+
|
|
322
|
+
entities["instances"].add(uri)
|
|
323
|
+
|
|
324
|
+
return entities
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def collect_diagram_entities(
|
|
328
|
+
graph: Graph, context: UMLContext, selectors: dict[str, str]
|
|
329
|
+
) -> dict[str, set[URIRef]]:
|
|
330
|
+
"""Collect all entities for a UML diagram based on context.
|
|
331
|
+
|
|
332
|
+
This is the main entry point for entity selection. It orchestrates
|
|
333
|
+
the selection of classes, properties, and instances based on the
|
|
334
|
+
context mode (default or explicit).
|
|
335
|
+
|
|
336
|
+
Args:
|
|
337
|
+
graph: RDF graph to select from
|
|
338
|
+
context: UML context specifying selection criteria
|
|
339
|
+
selectors: Selector definitions from config
|
|
340
|
+
|
|
341
|
+
Returns:
|
|
342
|
+
Dictionary with keys:
|
|
343
|
+
- 'classes': Selected class URIRefs
|
|
344
|
+
- 'object_properties': Selected object property URIRefs
|
|
345
|
+
- 'datatype_properties': Selected datatype property URIRefs
|
|
346
|
+
- 'annotation_properties': Selected annotation property URIRefs
|
|
347
|
+
- 'instances': Selected instance URIRefs
|
|
348
|
+
"""
|
|
349
|
+
# Handle explicit mode (direct specification of classes, properties, attributes, & instances)
|
|
350
|
+
if context.mode == "explicit":
|
|
351
|
+
return collect_explicit_entities(graph, context)
|
|
352
|
+
|
|
353
|
+
# Default mode: use existing selection strategies
|
|
354
|
+
# Select classes
|
|
355
|
+
classes = select_classes(graph, context, selectors)
|
|
356
|
+
|
|
357
|
+
# Select properties based on classes
|
|
358
|
+
properties = select_properties(graph, context, classes)
|
|
359
|
+
|
|
360
|
+
# Select instances if requested
|
|
361
|
+
instances = set()
|
|
362
|
+
if context.include_instances:
|
|
363
|
+
instances = select_instances(graph, classes)
|
|
364
|
+
|
|
365
|
+
return {
|
|
366
|
+
"classes": classes,
|
|
367
|
+
"object_properties": properties["object"],
|
|
368
|
+
"datatype_properties": properties["datatype"],
|
|
369
|
+
"annotation_properties": properties["annotation"],
|
|
370
|
+
"instances": instances,
|
|
371
|
+
}
|