dsp-tools 0.9.13__py3-none-any.whl → 18.3.0.post13__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.
Files changed (348) hide show
  1. dsp_tools/__init__.py +5 -0
  2. dsp_tools/cli/args.py +47 -0
  3. dsp_tools/cli/call_action.py +85 -0
  4. dsp_tools/cli/call_action_files_only.py +101 -0
  5. dsp_tools/cli/call_action_with_network.py +207 -0
  6. dsp_tools/cli/create_parsers.py +479 -0
  7. dsp_tools/cli/entry_point.py +322 -0
  8. dsp_tools/cli/utils.py +87 -0
  9. dsp_tools/clients/CLAUDE.md +420 -0
  10. dsp_tools/clients/authentication_client.py +14 -0
  11. dsp_tools/clients/authentication_client_live.py +66 -0
  12. dsp_tools/clients/connection.py +35 -0
  13. dsp_tools/clients/connection_live.py +233 -0
  14. dsp_tools/clients/fuseki_metrics.py +60 -0
  15. dsp_tools/clients/group_user_clients.py +35 -0
  16. dsp_tools/clients/group_user_clients_live.py +181 -0
  17. dsp_tools/clients/legal_info_client.py +23 -0
  18. dsp_tools/clients/legal_info_client_live.py +132 -0
  19. dsp_tools/clients/list_client.py +49 -0
  20. dsp_tools/clients/list_client_live.py +166 -0
  21. dsp_tools/clients/metadata_client.py +24 -0
  22. dsp_tools/clients/metadata_client_live.py +47 -0
  23. dsp_tools/clients/ontology_clients.py +49 -0
  24. dsp_tools/clients/ontology_create_client_live.py +166 -0
  25. dsp_tools/clients/ontology_get_client_live.py +80 -0
  26. dsp_tools/clients/permissions_client.py +68 -0
  27. dsp_tools/clients/project_client.py +16 -0
  28. dsp_tools/clients/project_client_live.py +66 -0
  29. dsp_tools/commands/create/communicate_problems.py +24 -0
  30. dsp_tools/commands/create/create.py +134 -0
  31. dsp_tools/commands/create/create_on_server/cardinalities.py +111 -0
  32. dsp_tools/commands/create/create_on_server/classes.py +99 -0
  33. dsp_tools/commands/create/create_on_server/complete_ontologies.py +116 -0
  34. dsp_tools/commands/create/create_on_server/default_permissions.py +134 -0
  35. dsp_tools/commands/create/create_on_server/group_users.py +165 -0
  36. dsp_tools/commands/create/create_on_server/lists.py +163 -0
  37. dsp_tools/commands/create/create_on_server/mappers.py +12 -0
  38. dsp_tools/commands/create/create_on_server/onto_utils.py +74 -0
  39. dsp_tools/commands/create/create_on_server/ontology.py +52 -0
  40. dsp_tools/commands/create/create_on_server/project.py +68 -0
  41. dsp_tools/commands/create/create_on_server/properties.py +119 -0
  42. dsp_tools/commands/create/exceptions.py +29 -0
  43. dsp_tools/commands/create/lists_only.py +66 -0
  44. dsp_tools/commands/create/models/create_problems.py +87 -0
  45. dsp_tools/commands/create/models/parsed_ontology.py +88 -0
  46. dsp_tools/commands/create/models/parsed_project.py +81 -0
  47. dsp_tools/commands/create/models/rdf_ontology.py +12 -0
  48. dsp_tools/commands/create/models/server_project_info.py +100 -0
  49. dsp_tools/commands/create/parsing/parse_lists.py +45 -0
  50. dsp_tools/commands/create/parsing/parse_ontology.py +243 -0
  51. dsp_tools/commands/create/parsing/parse_project.py +149 -0
  52. dsp_tools/commands/create/parsing/parsing_utils.py +40 -0
  53. dsp_tools/commands/create/project_validate.py +595 -0
  54. dsp_tools/commands/create/serialisation/ontology.py +119 -0
  55. dsp_tools/commands/create/serialisation/project.py +44 -0
  56. dsp_tools/commands/excel2json/CLAUDE.md +101 -0
  57. dsp_tools/commands/excel2json/json_header.py +321 -0
  58. dsp_tools/commands/excel2json/lists/__init__.py +0 -0
  59. dsp_tools/commands/excel2json/lists/compliance_checks.py +292 -0
  60. dsp_tools/commands/excel2json/lists/make_lists.py +247 -0
  61. dsp_tools/commands/excel2json/lists/models/__init__.py +0 -0
  62. dsp_tools/commands/excel2json/lists/models/deserialise.py +30 -0
  63. dsp_tools/commands/excel2json/lists/models/input_error.py +216 -0
  64. dsp_tools/commands/excel2json/lists/models/serialise.py +57 -0
  65. dsp_tools/commands/excel2json/lists/utils.py +81 -0
  66. dsp_tools/commands/excel2json/models/__init__.py +0 -0
  67. dsp_tools/commands/excel2json/models/input_error.py +416 -0
  68. dsp_tools/commands/excel2json/models/json_header.py +175 -0
  69. dsp_tools/commands/excel2json/models/list_node_name.py +16 -0
  70. dsp_tools/commands/excel2json/models/ontology.py +76 -0
  71. dsp_tools/commands/excel2json/old_lists.py +328 -0
  72. dsp_tools/commands/excel2json/project.py +280 -0
  73. dsp_tools/commands/excel2json/properties.py +370 -0
  74. dsp_tools/commands/excel2json/resources.py +336 -0
  75. dsp_tools/commands/excel2json/utils.py +352 -0
  76. dsp_tools/commands/excel2xml/__init__.py +7 -0
  77. dsp_tools/commands/excel2xml/excel2xml_cli.py +523 -0
  78. dsp_tools/commands/excel2xml/excel2xml_lib.py +1953 -0
  79. dsp_tools/commands/excel2xml/propertyelement.py +47 -0
  80. dsp_tools/commands/get/__init__.py +0 -0
  81. dsp_tools/commands/get/get.py +166 -0
  82. dsp_tools/commands/get/get_permissions.py +257 -0
  83. dsp_tools/commands/get/get_permissions_legacy.py +89 -0
  84. dsp_tools/commands/get/legacy_models/__init__.py +0 -0
  85. dsp_tools/commands/get/legacy_models/context.py +318 -0
  86. dsp_tools/commands/get/legacy_models/group.py +241 -0
  87. dsp_tools/commands/get/legacy_models/helpers.py +47 -0
  88. dsp_tools/commands/get/legacy_models/listnode.py +390 -0
  89. dsp_tools/commands/get/legacy_models/model.py +12 -0
  90. dsp_tools/commands/get/legacy_models/ontology.py +324 -0
  91. dsp_tools/commands/get/legacy_models/project.py +366 -0
  92. dsp_tools/commands/get/legacy_models/propertyclass.py +417 -0
  93. dsp_tools/commands/get/legacy_models/resourceclass.py +676 -0
  94. dsp_tools/commands/get/legacy_models/user.py +438 -0
  95. dsp_tools/commands/get/models/__init__.py +0 -0
  96. dsp_tools/commands/get/models/permissions_models.py +10 -0
  97. dsp_tools/commands/id2iri.py +258 -0
  98. dsp_tools/commands/ingest_xmlupload/__init__.py +0 -0
  99. dsp_tools/commands/ingest_xmlupload/bulk_ingest_client.py +178 -0
  100. dsp_tools/commands/ingest_xmlupload/create_resources/__init__.py +0 -0
  101. dsp_tools/commands/ingest_xmlupload/create_resources/apply_ingest_id.py +69 -0
  102. dsp_tools/commands/ingest_xmlupload/create_resources/upload_xml.py +166 -0
  103. dsp_tools/commands/ingest_xmlupload/create_resources/user_information.py +121 -0
  104. dsp_tools/commands/ingest_xmlupload/ingest_files/__init__.py +0 -0
  105. dsp_tools/commands/ingest_xmlupload/ingest_files/ingest_files.py +64 -0
  106. dsp_tools/commands/ingest_xmlupload/upload_files/__init__.py +0 -0
  107. dsp_tools/commands/ingest_xmlupload/upload_files/filechecker.py +20 -0
  108. dsp_tools/commands/ingest_xmlupload/upload_files/input_error.py +57 -0
  109. dsp_tools/commands/ingest_xmlupload/upload_files/upload_failures.py +66 -0
  110. dsp_tools/commands/ingest_xmlupload/upload_files/upload_files.py +67 -0
  111. dsp_tools/commands/resume_xmlupload/__init__.py +0 -0
  112. dsp_tools/commands/resume_xmlupload/resume_xmlupload.py +96 -0
  113. dsp_tools/commands/start_stack.py +428 -0
  114. dsp_tools/commands/update_legal/CLAUDE.md +344 -0
  115. dsp_tools/commands/update_legal/__init__.py +0 -0
  116. dsp_tools/commands/update_legal/core.py +182 -0
  117. dsp_tools/commands/update_legal/csv_operations.py +135 -0
  118. dsp_tools/commands/update_legal/models.py +87 -0
  119. dsp_tools/commands/update_legal/xml_operations.py +247 -0
  120. dsp_tools/commands/validate_data/CLAUDE.md +159 -0
  121. dsp_tools/commands/validate_data/__init__.py +0 -0
  122. dsp_tools/commands/validate_data/constants.py +59 -0
  123. dsp_tools/commands/validate_data/mappers.py +143 -0
  124. dsp_tools/commands/validate_data/models/__init__.py +0 -0
  125. dsp_tools/commands/validate_data/models/api_responses.py +45 -0
  126. dsp_tools/commands/validate_data/models/input_problems.py +119 -0
  127. dsp_tools/commands/validate_data/models/rdf_like_data.py +117 -0
  128. dsp_tools/commands/validate_data/models/validation.py +106 -0
  129. dsp_tools/commands/validate_data/prepare_data/__init__.py +0 -0
  130. dsp_tools/commands/validate_data/prepare_data/get_rdf_like_data.py +296 -0
  131. dsp_tools/commands/validate_data/prepare_data/make_data_graph.py +91 -0
  132. dsp_tools/commands/validate_data/prepare_data/prepare_data.py +184 -0
  133. dsp_tools/commands/validate_data/process_validation_report/__init__.py +0 -0
  134. dsp_tools/commands/validate_data/process_validation_report/get_user_validation_message.py +358 -0
  135. dsp_tools/commands/validate_data/process_validation_report/query_validation_result.py +507 -0
  136. dsp_tools/commands/validate_data/process_validation_report/reformat_validation_results.py +150 -0
  137. dsp_tools/commands/validate_data/shacl_cli_validator.py +70 -0
  138. dsp_tools/commands/validate_data/sparql/__init__.py +0 -0
  139. dsp_tools/commands/validate_data/sparql/cardinality_shacl.py +209 -0
  140. dsp_tools/commands/validate_data/sparql/construct_shacl.py +92 -0
  141. dsp_tools/commands/validate_data/sparql/legal_info_shacl.py +36 -0
  142. dsp_tools/commands/validate_data/sparql/value_shacl.py +357 -0
  143. dsp_tools/commands/validate_data/utils.py +59 -0
  144. dsp_tools/commands/validate_data/validate_data.py +283 -0
  145. dsp_tools/commands/validate_data/validation/__init__.py +0 -0
  146. dsp_tools/commands/validate_data/validation/check_duplicate_files.py +55 -0
  147. dsp_tools/commands/validate_data/validation/check_for_unknown_classes.py +67 -0
  148. dsp_tools/commands/validate_data/validation/get_validation_report.py +94 -0
  149. dsp_tools/commands/validate_data/validation/validate_ontology.py +107 -0
  150. dsp_tools/commands/xmlupload/CLAUDE.md +292 -0
  151. dsp_tools/commands/xmlupload/__init__.py +0 -0
  152. dsp_tools/commands/xmlupload/iri_resolver.py +21 -0
  153. dsp_tools/commands/xmlupload/make_rdf_graph/__init__.py +0 -0
  154. dsp_tools/commands/xmlupload/make_rdf_graph/constants.py +63 -0
  155. dsp_tools/commands/xmlupload/make_rdf_graph/jsonld_utils.py +44 -0
  156. dsp_tools/commands/xmlupload/make_rdf_graph/make_file_value.py +77 -0
  157. dsp_tools/commands/xmlupload/make_rdf_graph/make_resource_and_values.py +114 -0
  158. dsp_tools/commands/xmlupload/make_rdf_graph/make_values.py +262 -0
  159. dsp_tools/commands/xmlupload/models/__init__.py +0 -0
  160. dsp_tools/commands/xmlupload/models/bitstream_info.py +18 -0
  161. dsp_tools/commands/xmlupload/models/formatted_text_value.py +10 -0
  162. dsp_tools/commands/xmlupload/models/ingest.py +143 -0
  163. dsp_tools/commands/xmlupload/models/input_problems.py +58 -0
  164. dsp_tools/commands/xmlupload/models/lookup_models.py +21 -0
  165. dsp_tools/commands/xmlupload/models/permission.py +45 -0
  166. dsp_tools/commands/xmlupload/models/permissions_parsed.py +93 -0
  167. dsp_tools/commands/xmlupload/models/processed/__init__.py +0 -0
  168. dsp_tools/commands/xmlupload/models/processed/file_values.py +29 -0
  169. dsp_tools/commands/xmlupload/models/processed/res.py +27 -0
  170. dsp_tools/commands/xmlupload/models/processed/values.py +101 -0
  171. dsp_tools/commands/xmlupload/models/rdf_models.py +26 -0
  172. dsp_tools/commands/xmlupload/models/upload_clients.py +14 -0
  173. dsp_tools/commands/xmlupload/models/upload_state.py +20 -0
  174. dsp_tools/commands/xmlupload/prepare_xml_input/__init__.py +0 -0
  175. dsp_tools/commands/xmlupload/prepare_xml_input/ark2iri.py +55 -0
  176. dsp_tools/commands/xmlupload/prepare_xml_input/get_processed_resources.py +252 -0
  177. dsp_tools/commands/xmlupload/prepare_xml_input/iiif_uri_validator.py +50 -0
  178. dsp_tools/commands/xmlupload/prepare_xml_input/list_client.py +120 -0
  179. dsp_tools/commands/xmlupload/prepare_xml_input/prepare_xml_input.py +67 -0
  180. dsp_tools/commands/xmlupload/prepare_xml_input/read_validate_xml_file.py +58 -0
  181. dsp_tools/commands/xmlupload/prepare_xml_input/transform_input_values.py +118 -0
  182. dsp_tools/commands/xmlupload/resource_create_client.py +25 -0
  183. dsp_tools/commands/xmlupload/richtext_id2iri.py +37 -0
  184. dsp_tools/commands/xmlupload/stash/__init__.py +0 -0
  185. dsp_tools/commands/xmlupload/stash/analyse_circular_reference_graph.py +236 -0
  186. dsp_tools/commands/xmlupload/stash/create_info_for_graph.py +53 -0
  187. dsp_tools/commands/xmlupload/stash/graph_models.py +87 -0
  188. dsp_tools/commands/xmlupload/stash/stash_circular_references.py +68 -0
  189. dsp_tools/commands/xmlupload/stash/stash_models.py +109 -0
  190. dsp_tools/commands/xmlupload/stash/upload_stashed_resptr_props.py +106 -0
  191. dsp_tools/commands/xmlupload/stash/upload_stashed_xml_texts.py +196 -0
  192. dsp_tools/commands/xmlupload/upload_config.py +76 -0
  193. dsp_tools/commands/xmlupload/write_diagnostic_info.py +27 -0
  194. dsp_tools/commands/xmlupload/xmlupload.py +516 -0
  195. dsp_tools/config/__init__.py +0 -0
  196. dsp_tools/config/logger_config.py +69 -0
  197. dsp_tools/config/warnings_config.py +32 -0
  198. dsp_tools/error/__init__.py +0 -0
  199. dsp_tools/error/custom_warnings.py +39 -0
  200. dsp_tools/error/exceptions.py +204 -0
  201. dsp_tools/error/problems.py +10 -0
  202. dsp_tools/error/xmllib_errors.py +20 -0
  203. dsp_tools/error/xmllib_warnings.py +54 -0
  204. dsp_tools/error/xmllib_warnings_util.py +159 -0
  205. dsp_tools/error/xsd_validation_error_msg.py +19 -0
  206. dsp_tools/legacy_models/__init__.py +0 -0
  207. dsp_tools/legacy_models/datetimestamp.py +81 -0
  208. dsp_tools/legacy_models/langstring.py +253 -0
  209. dsp_tools/legacy_models/projectContext.py +49 -0
  210. dsp_tools/py.typed +0 -0
  211. dsp_tools/resources/schema/data.xsd +648 -0
  212. dsp_tools/resources/schema/lists-only.json +72 -0
  213. dsp_tools/resources/schema/project.json +1258 -0
  214. dsp_tools/resources/schema/properties-only.json +874 -0
  215. dsp_tools/resources/schema/resources-only.json +140 -0
  216. dsp_tools/resources/start-stack/docker-compose.override-host.j2 +11 -0
  217. dsp_tools/resources/start-stack/docker-compose.override.yml +11 -0
  218. dsp_tools/resources/start-stack/docker-compose.yml +88 -0
  219. dsp_tools/resources/start-stack/dsp-app-config.json +45 -0
  220. dsp_tools/resources/start-stack/dsp-app-config.override-host.j2 +26 -0
  221. dsp_tools/resources/validate_data/api-shapes-resource-cardinalities.ttl +191 -0
  222. dsp_tools/resources/validate_data/api-shapes.ttl +804 -0
  223. dsp_tools/resources/validate_data/shacl-cli-image.yml +4 -0
  224. dsp_tools/resources/validate_data/validate-ontology.ttl +99 -0
  225. dsp_tools/utils/__init__.py +0 -0
  226. dsp_tools/utils/ansi_colors.py +32 -0
  227. dsp_tools/utils/data_formats/__init__.py +0 -0
  228. dsp_tools/utils/data_formats/date_util.py +166 -0
  229. dsp_tools/utils/data_formats/iri_util.py +30 -0
  230. dsp_tools/utils/data_formats/shared.py +81 -0
  231. dsp_tools/utils/data_formats/uri_util.py +76 -0
  232. dsp_tools/utils/fuseki_bloating.py +63 -0
  233. dsp_tools/utils/json_parsing.py +22 -0
  234. dsp_tools/utils/rdf_constants.py +42 -0
  235. dsp_tools/utils/rdflib_utils.py +10 -0
  236. dsp_tools/utils/replace_id_with_iri.py +66 -0
  237. dsp_tools/utils/request_utils.py +238 -0
  238. dsp_tools/utils/xml_parsing/__init__.py +0 -0
  239. dsp_tools/utils/xml_parsing/get_lookups.py +32 -0
  240. dsp_tools/utils/xml_parsing/get_parsed_resources.py +325 -0
  241. dsp_tools/utils/xml_parsing/models/__init__.py +0 -0
  242. dsp_tools/utils/xml_parsing/models/parsed_resource.py +76 -0
  243. dsp_tools/utils/xml_parsing/parse_clean_validate_xml.py +137 -0
  244. dsp_tools/xmllib/CLAUDE.md +302 -0
  245. dsp_tools/xmllib/__init__.py +49 -0
  246. dsp_tools/xmllib/general_functions.py +877 -0
  247. dsp_tools/xmllib/internal/__init__.py +0 -0
  248. dsp_tools/xmllib/internal/checkers.py +162 -0
  249. dsp_tools/xmllib/internal/circumvent_circular_imports.py +36 -0
  250. dsp_tools/xmllib/internal/constants.py +46 -0
  251. dsp_tools/xmllib/internal/input_converters.py +155 -0
  252. dsp_tools/xmllib/internal/serialise_file_value.py +57 -0
  253. dsp_tools/xmllib/internal/serialise_resource.py +177 -0
  254. dsp_tools/xmllib/internal/serialise_values.py +152 -0
  255. dsp_tools/xmllib/internal/type_aliases.py +11 -0
  256. dsp_tools/xmllib/models/__init__.py +0 -0
  257. dsp_tools/xmllib/models/config_options.py +28 -0
  258. dsp_tools/xmllib/models/date_formats.py +48 -0
  259. dsp_tools/xmllib/models/dsp_base_resources.py +1542 -0
  260. dsp_tools/xmllib/models/internal/__init__.py +0 -0
  261. dsp_tools/xmllib/models/internal/file_values.py +172 -0
  262. dsp_tools/xmllib/models/internal/geometry.py +162 -0
  263. dsp_tools/xmllib/models/internal/migration_metadata.py +55 -0
  264. dsp_tools/xmllib/models/internal/serialise_permissions.py +66 -0
  265. dsp_tools/xmllib/models/internal/values.py +342 -0
  266. dsp_tools/xmllib/models/licenses/__init__.py +0 -0
  267. dsp_tools/xmllib/models/licenses/other.py +59 -0
  268. dsp_tools/xmllib/models/licenses/recommended.py +107 -0
  269. dsp_tools/xmllib/models/permissions.py +41 -0
  270. dsp_tools/xmllib/models/res.py +1782 -0
  271. dsp_tools/xmllib/models/root.py +348 -0
  272. dsp_tools/xmllib/value_checkers.py +434 -0
  273. dsp_tools/xmllib/value_converters.py +777 -0
  274. dsp_tools-18.3.0.post13.dist-info/METADATA +90 -0
  275. dsp_tools-18.3.0.post13.dist-info/RECORD +286 -0
  276. dsp_tools-18.3.0.post13.dist-info/WHEEL +4 -0
  277. dsp_tools-18.3.0.post13.dist-info/entry_points.txt +3 -0
  278. dsp_tools-0.9.13.dist-info/LICENSE +0 -674
  279. dsp_tools-0.9.13.dist-info/METADATA +0 -144
  280. dsp_tools-0.9.13.dist-info/RECORD +0 -71
  281. dsp_tools-0.9.13.dist-info/WHEEL +0 -5
  282. dsp_tools-0.9.13.dist-info/entry_points.txt +0 -3
  283. dsp_tools-0.9.13.dist-info/top_level.txt +0 -1
  284. dsplib/models/connection.py +0 -272
  285. dsplib/models/group.py +0 -296
  286. dsplib/models/helpers.py +0 -505
  287. dsplib/models/langstring.py +0 -277
  288. dsplib/models/listnode.py +0 -578
  289. dsplib/models/model.py +0 -20
  290. dsplib/models/ontology.py +0 -448
  291. dsplib/models/permission.py +0 -112
  292. dsplib/models/project.py +0 -547
  293. dsplib/models/propertyclass.py +0 -505
  294. dsplib/models/resource.py +0 -366
  295. dsplib/models/resourceclass.py +0 -810
  296. dsplib/models/sipi.py +0 -30
  297. dsplib/models/user.py +0 -731
  298. dsplib/models/value.py +0 -1000
  299. dsplib/utils/knora-data-schema.xsd +0 -454
  300. dsplib/utils/knora-schema-lists.json +0 -83
  301. dsplib/utils/knora-schema.json +0 -434
  302. dsplib/utils/onto_commons.py +0 -24
  303. dsplib/utils/onto_create_lists.py +0 -73
  304. dsplib/utils/onto_create_ontology.py +0 -442
  305. dsplib/utils/onto_get.py +0 -58
  306. dsplib/utils/onto_validate.py +0 -33
  307. dsplib/utils/xml_upload.py +0 -539
  308. dsplib/widgets/doublepassword.py +0 -80
  309. knora/MLS-import-libraries.py +0 -84
  310. knora/dsp_tools.py +0 -96
  311. knora/dsplib/models/connection.py +0 -272
  312. knora/dsplib/models/group.py +0 -296
  313. knora/dsplib/models/helpers.py +0 -506
  314. knora/dsplib/models/langstring.py +0 -277
  315. knora/dsplib/models/listnode.py +0 -578
  316. knora/dsplib/models/model.py +0 -20
  317. knora/dsplib/models/ontology.py +0 -448
  318. knora/dsplib/models/permission.py +0 -112
  319. knora/dsplib/models/project.py +0 -583
  320. knora/dsplib/models/propertyclass.py +0 -505
  321. knora/dsplib/models/resource.py +0 -416
  322. knora/dsplib/models/resourceclass.py +0 -811
  323. knora/dsplib/models/sipi.py +0 -35
  324. knora/dsplib/models/user.py +0 -731
  325. knora/dsplib/models/value.py +0 -1000
  326. knora/dsplib/utils/knora-data-schema.xsd +0 -464
  327. knora/dsplib/utils/knora-schema-lists.json +0 -83
  328. knora/dsplib/utils/knora-schema.json +0 -444
  329. knora/dsplib/utils/onto_commons.py +0 -24
  330. knora/dsplib/utils/onto_create_lists.py +0 -73
  331. knora/dsplib/utils/onto_create_ontology.py +0 -451
  332. knora/dsplib/utils/onto_get.py +0 -58
  333. knora/dsplib/utils/onto_validate.py +0 -33
  334. knora/dsplib/utils/xml_upload.py +0 -540
  335. knora/dsplib/widgets/doublepassword.py +0 -80
  336. knora/knora.py +0 -2108
  337. knora/test.py +0 -99
  338. knora/testit.py +0 -76
  339. knora/xml2knora.py +0 -633
  340. {dsplib → dsp_tools/cli}/__init__.py +0 -0
  341. {dsplib/models → dsp_tools/clients}/__init__.py +0 -0
  342. {dsplib/utils → dsp_tools/commands}/__init__.py +0 -0
  343. {dsplib/widgets → dsp_tools/commands/create}/__init__.py +0 -0
  344. {knora → dsp_tools/commands/create/create_on_server}/__init__.py +0 -0
  345. {knora/dsplib → dsp_tools/commands/create/models}/__init__.py +0 -0
  346. {knora/dsplib/models → dsp_tools/commands/create/parsing}/__init__.py +0 -0
  347. {knora/dsplib/utils → dsp_tools/commands/create/serialisation}/__init__.py +0 -0
  348. {knora/dsplib/widgets → dsp_tools/commands/excel2json}/__init__.py +0 -0
@@ -0,0 +1,676 @@
1
+ """
2
+ This model implements the handling of resource classes. It contains two classes that work closely together:
3
+ * "HasProperty" deals with the association of Property-instances with the Resource-instances. This association
4
+ is done using the "cardinality"-clause
5
+ * "ResourceClass" is the main class representing a DSP resource class.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ from collections.abc import Sequence
11
+ from enum import Enum
12
+ from typing import Any
13
+ from typing import Optional
14
+ from typing import Union
15
+
16
+ import regex
17
+
18
+ from dsp_tools.clients.connection import Connection
19
+ from dsp_tools.commands.get.legacy_models.context import Context
20
+ from dsp_tools.commands.get.legacy_models.helpers import Cardinality
21
+ from dsp_tools.commands.get.legacy_models.model import Model
22
+ from dsp_tools.error.exceptions import BaseError
23
+ from dsp_tools.legacy_models.datetimestamp import DateTimeStamp
24
+ from dsp_tools.legacy_models.langstring import LangString
25
+
26
+
27
+ class HasProperty(Model):
28
+ ROUTE: str = "/v2/ontologies/cardinalities"
29
+
30
+ class Ptype(Enum):
31
+ system = 1
32
+ knora = 2
33
+ other = 3
34
+
35
+ _context: Context
36
+ _ontology_id: str
37
+ _property_id: str
38
+ _resclass_id: str
39
+ _cardinality: Cardinality
40
+ _gui_order: int
41
+ _ptype: Ptype
42
+
43
+ def __init__(
44
+ self,
45
+ con: Connection,
46
+ context: Context,
47
+ ontology_id: Optional[str] = None,
48
+ property_id: Optional[str] = None,
49
+ resclass_id: Optional[str] = None,
50
+ cardinality: Optional[Cardinality] = None,
51
+ gui_order: Optional[int] = None,
52
+ ptype: Optional[Ptype] = None,
53
+ ):
54
+ super().__init__(con)
55
+ if not isinstance(context, Context):
56
+ raise BaseError('"context"-parameter must be an instance of Context')
57
+ self._context = context
58
+ if ontology_id is not None:
59
+ self._ontology_id = context.iri_from_prefix(ontology_id)
60
+ else:
61
+ self._ontology_id = None
62
+ self._property_id = property_id
63
+ self._resclass_id = resclass_id
64
+ self._cardinality = cardinality
65
+ self._gui_order = gui_order
66
+ self._ptype = ptype
67
+ self._changed = set()
68
+
69
+ #
70
+ # Here follows a list of getters/setters
71
+ #
72
+ @property
73
+ def ontology_id(self) -> Optional[str]:
74
+ return self._ontology_id
75
+
76
+ @ontology_id.setter
77
+ def ontology_id(self, value: Optional[str]) -> None:
78
+ self._ontology_id = value
79
+
80
+ @property
81
+ def property_id(self) -> Optional[str]:
82
+ return self._property_id
83
+
84
+ @property
85
+ def resclass_id(self) -> Optional[str]:
86
+ return self._resclass_id
87
+
88
+ @resclass_id.setter
89
+ def resclass_id(self, value: Optional[str]) -> None:
90
+ self._resclass_id = value
91
+
92
+ @property
93
+ def cardinality(self) -> Optional[Cardinality]:
94
+ return self._cardinality
95
+
96
+ @cardinality.setter
97
+ def cardinality(self, value: Optional[Cardinality]) -> None:
98
+ self._cardinality = value
99
+ self._changed.add("cardinality")
100
+
101
+ @property
102
+ def gui_order(self) -> Optional[int]:
103
+ return self._gui_order
104
+
105
+ @gui_order.setter
106
+ def gui_order(self, value: int) -> None:
107
+ self._gui_order = value
108
+ self._changed.add("gui_order")
109
+
110
+ @property
111
+ def ptype(self) -> Ptype:
112
+ return self._ptype
113
+
114
+ @classmethod
115
+ def fromJsonObj(cls, con: Connection, context: Context, jsonld_obj: dict[str, Any]) -> tuple[str, HasProperty]:
116
+ rdf_iri = context.prefix_from_iri("http://www.w3.org/1999/02/22-rdf-syntax-ns#")
117
+ rdfs_iri = context.prefix_from_iri("http://www.w3.org/2000/01/rdf-schema#")
118
+ owl_iri = context.prefix_from_iri("http://www.w3.org/2002/07/owl#")
119
+ knora_api_iri = context.prefix_from_iri("http://api.knora.org/ontology/knora-api/v2#")
120
+ salsah_gui_iri = context.prefix_from_iri("http://api.knora.org/ontology/salsah-gui/v2#")
121
+
122
+ if jsonld_obj.get("@type") is None or jsonld_obj.get("@type") != owl_iri + ":Restriction":
123
+ raise BaseError("Expected restriction type")
124
+
125
+ cardinality = cls._fromJsonObj_get_cardinality(jsonld_obj, owl_iri)
126
+
127
+ ontology_id, property_id, ptype = cls._fromJsonObj_get_prop_type_iri(
128
+ context, jsonld_obj, knora_api_iri, owl_iri, rdf_iri, rdfs_iri
129
+ )
130
+
131
+ gui_order: int = None
132
+ if jsonld_obj.get(salsah_gui_iri + ":guiOrder") is not None:
133
+ gui_order = jsonld_obj[salsah_gui_iri + ":guiOrder"]
134
+ return property_id, cls(
135
+ con=con,
136
+ context=context,
137
+ ontology_id=ontology_id,
138
+ property_id=property_id,
139
+ cardinality=cardinality,
140
+ gui_order=gui_order,
141
+ ptype=ptype,
142
+ )
143
+
144
+ @staticmethod
145
+ def _fromJsonObj_get_prop_type_iri(
146
+ context: Context, jsonld_obj: dict[str, Any], knora_api_iri: str, owl_iri: str, rdf_iri: str, rdfs_iri: str
147
+ ) -> tuple[str, str, HasProperty.Ptype]:
148
+ property_id: str
149
+ ptype: HasProperty.Ptype
150
+ ontology_id: Optional[str] = None
151
+ if jsonld_obj.get(owl_iri + ":onProperty") is None:
152
+ raise BaseError("No property IRI given")
153
+ p = jsonld_obj[owl_iri + ":onProperty"].get("@id")
154
+ if p is None:
155
+ raise BaseError("No property IRI given")
156
+ pp = p.split(":")
157
+ if pp[0] == rdf_iri or pp[0] == rdfs_iri or pp[0] == owl_iri:
158
+ ptype = HasProperty.Ptype.system
159
+ elif pp[0] == knora_api_iri:
160
+ ptype = HasProperty.Ptype.knora
161
+ else:
162
+ ptype = HasProperty.Ptype.other
163
+ ontology_id = context.iri_from_prefix(pp[0])
164
+ property_id = p
165
+ return ontology_id, property_id, ptype
166
+
167
+ @staticmethod
168
+ def _fromJsonObj_get_cardinality(jsonld_obj: dict[str, Any], owl_iri: str):
169
+ cardinality: Cardinality
170
+ if jsonld_obj.get(owl_iri + ":cardinality") is not None:
171
+ cardinality = Cardinality.C_1
172
+ elif jsonld_obj.get(owl_iri + ":maxCardinality") is not None:
173
+ cardinality = Cardinality.C_0_1
174
+ elif jsonld_obj.get(owl_iri + ":minCardinality") is not None:
175
+ if jsonld_obj.get(owl_iri + ":minCardinality") == 0:
176
+ cardinality = Cardinality.C_0_n
177
+ elif jsonld_obj.get(owl_iri + ":minCardinality") == 1:
178
+ cardinality = Cardinality.C_1_n
179
+ else:
180
+ raise BaseError("Problem with cardinality")
181
+ else:
182
+ raise BaseError("Problem with cardinality")
183
+ return cardinality
184
+
185
+ def create(self, last_modification_date: DateTimeStamp) -> tuple[DateTimeStamp, ResourceClass]:
186
+ if self._ontology_id is None:
187
+ raise BaseError("Ontology id required")
188
+ if self._property_id is None:
189
+ raise BaseError("Property id required")
190
+ if self._cardinality is None:
191
+ raise BaseError("Cardinality id required")
192
+
193
+ jsonobj = self._toJsonObj_create(last_modification_date)
194
+ result = self._con.post(HasProperty.ROUTE, jsonobj)
195
+ last_modification_date = DateTimeStamp(result["knora-api:lastModificationDate"])
196
+ return last_modification_date, ResourceClass.fromJsonObj(self._con, self._context, result["@graph"])
197
+
198
+ def update(self, last_modification_date: DateTimeStamp) -> tuple[DateTimeStamp, ResourceClass]:
199
+ if self._ontology_id is None:
200
+ raise BaseError("Ontology id required")
201
+ if self._property_id is None:
202
+ raise BaseError("Property id required")
203
+ if self._cardinality is None:
204
+ raise BaseError("Cardinality id required")
205
+ jsonobj = self._toJsonObj_update(last_modification_date)
206
+ result = self._con.put(HasProperty.ROUTE, jsonobj)
207
+ last_modification_date = DateTimeStamp(result["knora-api:lastModificationDate"])
208
+ return last_modification_date, ResourceClass.fromJsonObj(self._con, self._context, result["@graph"])
209
+
210
+ def _toJsonObj_update(self, lastModificationDate: DateTimeStamp) -> dict[str, Any]:
211
+ occurrence = self._toJsonObj_get_owl_cardinality()
212
+ tmp = {
213
+ "@id": self._ontology_id,
214
+ "@type": "owl:Ontology",
215
+ "knora-api:lastModificationDate": lastModificationDate.toJsonObj(),
216
+ "@graph": [
217
+ {
218
+ "@id": self._resclass_id,
219
+ "@type": "owl:Class",
220
+ "rdfs:subClassOf": {
221
+ "@type": "owl:Restriction",
222
+ occurrence[0]: occurrence[1],
223
+ "owl:onProperty": {"@id": self._property_id},
224
+ },
225
+ }
226
+ ],
227
+ "@context": self._context.toJsonObj(),
228
+ }
229
+ if self._gui_order is not None and "gui_order" in self._changed:
230
+ tmp["@graph"][0]["rdfs:subClassOf"]["salsah-gui:guiOrder"] = self._gui_order
231
+ return tmp
232
+
233
+ def _toJsonObj_create(self, lastModificationDate: DateTimeStamp) -> dict[str, Any]:
234
+ occurrence = self._toJsonObj_get_owl_cardinality()
235
+ tmp = {
236
+ "@id": self._ontology_id,
237
+ "@type": "owl:Ontology",
238
+ "knora-api:lastModificationDate": lastModificationDate.toJsonObj(),
239
+ "@graph": [
240
+ {
241
+ "@id": self._resclass_id,
242
+ "@type": "owl:Class",
243
+ "rdfs:subClassOf": {
244
+ "@type": "owl:Restriction",
245
+ occurrence[0]: occurrence[1],
246
+ "owl:onProperty": {"@id": self._property_id},
247
+ },
248
+ }
249
+ ],
250
+ "@context": self._context.toJsonObj(),
251
+ }
252
+ if self._gui_order is not None:
253
+ tmp["@graph"][0]["rdfs:subClassOf"]["salsah-gui:guiOrder"] = self._gui_order
254
+ return tmp
255
+
256
+ def _toJsonObj_get_owl_cardinality(self) -> tuple[str, int]:
257
+ if self._cardinality is None:
258
+ raise BaseError("There must be a cardinality given!")
259
+ switcher = {
260
+ Cardinality.C_1: ("owl:cardinality", 1),
261
+ Cardinality.C_0_1: ("owl:maxCardinality", 1),
262
+ Cardinality.C_0_n: ("owl:minCardinality", 0),
263
+ Cardinality.C_1_n: ("owl:minCardinality", 1),
264
+ }
265
+ return switcher.get(self._cardinality)
266
+
267
+ def createDefinitionFileObj(self, context: Context, shortname: str) -> dict[str, Any]:
268
+ cardinality = {}
269
+ if self._ptype == HasProperty.Ptype.other or self.property_id in [
270
+ "knora-api:isPartOf",
271
+ "knora-api:seqnum",
272
+ ]:
273
+ cardinality["propname"] = context.reduce_iri(self._property_id, shortname)
274
+ cardinality["cardinality"] = self._cardinality.value
275
+ if self._gui_order is not None:
276
+ cardinality["gui_order"] = self._gui_order
277
+ return cardinality
278
+
279
+
280
+ class ResourceClass(Model):
281
+ """
282
+ This class represents a DSP resource class
283
+
284
+ Attributes
285
+ ----------
286
+
287
+ con : Connection
288
+ A Connection instance to a DSP server
289
+
290
+ iri : str
291
+ IRI of the ResourceClass [readonly, cannot be modified after creation of instance]
292
+
293
+ name: str
294
+ The name of the resource class, e.g. "Book", "Person", "Portait". Usually these names start
295
+ with a capital letter
296
+
297
+ ontology_id: str
298
+ The IRI/Id of the ontology this resource class belongs to
299
+
300
+ superclasses: str, list[str]
301
+ This is a list of superclasses for this resource class. Usually a project specific class must at least
302
+ be a subclass of "Resource", but can be subclassed of any other valid resource class. In addition, external
303
+ ontologies may be referenced:
304
+ e.g.:
305
+ ```
306
+ "super": "Resource"
307
+
308
+ "super": ":MySpecialTYpe"
309
+
310
+ "super": [":MySpecialType", "dcterms:BibliographicResource"]
311
+ ```
312
+
313
+ label: language dependent string, that is a dict like {"en": "Biblography", "de": "Literaturverzeichnis"}
314
+ A label (human readable name) for the resource
315
+
316
+ comment: language dependent string, that is a dict like {"en": "a comment", "de": "Ein Kommentar"}
317
+ A commentary to further explain what this resource class is used for
318
+
319
+ permission: str
320
+ The default permissions to be used if an instance of this resource class is being created
321
+
322
+ has_properties: dict[str, HasProperty]
323
+ Holds a dict with the property names as keys and a HasProperty instance. HasProperty holds
324
+ the information, how this resource class uses this property (basically the cardinality)
325
+
326
+ changed: bool
327
+ is set to True, if one of the fields has been chaned by the user (internal use only!)
328
+
329
+
330
+ Methods
331
+ -------
332
+
333
+ getProperty: Get information about a property defined for this resource class
334
+ getPropertery(prop_id: str) -> HasProperty
335
+ returns a HasProperty-instance
336
+
337
+ addProperty: Add a new property to the resource class
338
+ addProperty(property_id: str, cardinality: Cardinality, last_modification_date: DateTimeStamp)
339
+ -> Optional[DateTimeStamp]
340
+
341
+ create: Create a new resource class on the connected server
342
+
343
+ update: Update the information of a resource class on the connected server
344
+
345
+ delete: Mark a resource class as deleted (on the connected server)
346
+
347
+ createDefinitionFileObj: Create an object suitable for jsonification that conforms the the DSP-TOOLS ontology tools
348
+
349
+ print: Print the content of this class to the console
350
+
351
+ """
352
+
353
+ ROUTE: str = "/v2/ontologies/classes"
354
+
355
+ _context: Context
356
+ _iri: str
357
+ _name: str
358
+ _ontology_id: str
359
+ _superclasses: list[str]
360
+ _label: LangString
361
+ _comment: LangString
362
+ _permissions: str
363
+ _has_properties: dict[str, HasProperty]
364
+
365
+ def __init__(
366
+ self,
367
+ con: Connection,
368
+ context: Context,
369
+ iri: Optional[str] = None,
370
+ name: Optional[str] = None,
371
+ ontology_id: Optional[str] = None,
372
+ superclasses: Optional[Sequence[Union[ResourceClass, str]]] = None,
373
+ label: Optional[Union[LangString, str]] = None,
374
+ comment: Optional[Union[LangString, str]] = None,
375
+ permissions: Optional[str] = None,
376
+ has_properties: Optional[dict[str, HasProperty]] = None,
377
+ ):
378
+ """
379
+ Create an instance of ResourceClass
380
+
381
+ :param con:
382
+ :param context:
383
+ :param iri:
384
+ :param name:
385
+ :param ontology_id:
386
+ :param superclasses:
387
+ :param label:
388
+ :param comment:
389
+ :param permissions:
390
+ :param has_properties:
391
+ """
392
+ super().__init__(con)
393
+ self._context = context
394
+ self._iri = iri
395
+ self._name = name
396
+ if ontology_id is not None:
397
+ self._ontology_id = context.iri_from_prefix(ontology_id)
398
+ if isinstance(superclasses, ResourceClass):
399
+ self._superclasses = list(map(lambda a: a.iri, superclasses))
400
+ else:
401
+ self._superclasses = superclasses
402
+
403
+ self._label = self._check_process_langstring(label, "label")
404
+ self._comment = self._check_process_langstring(comment, "comment")
405
+ self._permissions = permissions
406
+ self._has_properties = has_properties
407
+ self._changed = set()
408
+
409
+ @staticmethod
410
+ def _check_process_langstring(langstring_to_check: None | str | LangString, what: str) -> LangString:
411
+ if langstring_to_check is not None:
412
+ if isinstance(langstring_to_check, str):
413
+ return LangString(langstring_to_check)
414
+ elif isinstance(langstring_to_check, LangString):
415
+ return langstring_to_check
416
+ else:
417
+ raise BaseError(f"Invalid LangString for {what}!")
418
+ else:
419
+ return LangString({})
420
+
421
+ #
422
+ # Here follows a list of getters/setters
423
+ #
424
+ @property
425
+ def name(self) -> Optional[str]:
426
+ return self._name
427
+
428
+ @property
429
+ def iri(self) -> Optional[str]:
430
+ return self._iri
431
+
432
+ @property
433
+ def ontology_id(self) -> Optional[str]:
434
+ return self._ontology_id
435
+
436
+ @property
437
+ def superclasses(self) -> Optional[list[str]]:
438
+ return self._superclasses
439
+
440
+ @property
441
+ def label(self) -> LangString:
442
+ return self._label
443
+
444
+ @label.setter
445
+ def label(self, value: Optional[Union[LangString, str]]) -> None:
446
+ if value is None:
447
+ self._label.empty() # clear all labels
448
+ elif isinstance(value, LangString):
449
+ self._label = value
450
+ elif isinstance(value, str):
451
+ self._label = LangString(value)
452
+ else:
453
+ raise BaseError("Not a valid LangString")
454
+ self._changed.add("label")
455
+
456
+ @property
457
+ def comment(self) -> LangString:
458
+ return self._comment
459
+
460
+ @comment.setter
461
+ def comment(self, value: Optional[LangString]) -> None:
462
+ if value is None:
463
+ self._comment.empty() # clear all comments!
464
+ elif isinstance(value, LangString):
465
+ self._comment = value
466
+ elif isinstance(value, str):
467
+ self._comment = LangString(value)
468
+ else:
469
+ raise BaseError("Not a valid LangString")
470
+ self._changed.add("comment")
471
+
472
+ @property
473
+ def permissions(self) -> Optional[str]:
474
+ return self._permissions
475
+
476
+ @property
477
+ def has_properties(self) -> dict[str, HasProperty]:
478
+ return self._has_properties
479
+
480
+ @classmethod
481
+ def fromJsonObj(cls, con: Connection, context: Context, json_obj: Any) -> ResourceClass:
482
+ if isinstance(json_obj, list):
483
+ json_obj = json_obj[0]
484
+ rdfs = context.prefix_from_iri("http://www.w3.org/2000/01/rdf-schema#")
485
+ owl = context.prefix_from_iri("http://www.w3.org/2002/07/owl#")
486
+ knora_api = context.prefix_from_iri("http://api.knora.org/ontology/knora-api/v2#")
487
+
488
+ if not (json_obj.get(knora_api + ":isResourceClass") or json_obj.get(knora_api + ":isStandoffClass")):
489
+ raise BaseError("This is not a resource!")
490
+
491
+ if json_obj.get("@id") is None:
492
+ raise BaseError('Resource class has no "@id"!')
493
+
494
+ tmp_id = json_obj.get("@id").split(":")
495
+ iri = context.iri_from_prefix(tmp_id[0]) + "#" + tmp_id[1]
496
+ ontology_id = tmp_id[0]
497
+ name = tmp_id[1]
498
+
499
+ has_properties, superclasses = cls._fromJsonObj_get_superclass(con, context, json_obj, rdfs, owl)
500
+
501
+ label = LangString.fromJsonLdObj(json_obj.get(rdfs + ":label"))
502
+ comment = LangString.fromJsonLdObj(json_obj.get(rdfs + ":comment"))
503
+ return cls(
504
+ con=con,
505
+ context=context,
506
+ name=name,
507
+ iri=iri,
508
+ ontology_id=ontology_id,
509
+ superclasses=superclasses,
510
+ label=label,
511
+ comment=comment,
512
+ has_properties=has_properties,
513
+ )
514
+
515
+ @staticmethod
516
+ def _fromJsonObj_get_superclass(
517
+ con: Connection, context: Context, json_obj: dict[str, Any], rdfs: str, owl: str
518
+ ) -> tuple[None | dict[str, HasProperty], None | list[str]]:
519
+ superclasses_obj = json_obj.get(rdfs + ":subClassOf")
520
+ if superclasses_obj is not None:
521
+ supercls = list(filter(lambda a: a.get("@id") is not None, superclasses_obj))
522
+ superclasses = list(map(lambda a: a["@id"], supercls))
523
+ has_props = list(filter(lambda a: a.get("@type") == (owl + ":Restriction"), superclasses_obj))
524
+ has_properties = dict(map(lambda a: HasProperty.fromJsonObj(con, context, a), has_props))
525
+ #
526
+ # now remove the ...Value stuff from resource pointers: A resource pointer is returned as 2 properties:
527
+ # one a direct link, the other the pointer to a link value
528
+ #
529
+ tmp = dict(has_properties)
530
+ for key in tmp.keys():
531
+ if key.endswith("Value"):
532
+ key_without_value = key.removesuffix("Value")
533
+ if key_without_value in has_properties:
534
+ del has_properties[key]
535
+ else:
536
+ superclasses = None
537
+ has_properties = None
538
+ return has_properties, superclasses
539
+
540
+ def create(self, last_modification_date: DateTimeStamp) -> tuple[DateTimeStamp, ResourceClass]:
541
+ jsonobj = self._toJsonObj_create(last_modification_date)
542
+ result = self._con.post(ResourceClass.ROUTE, jsonobj)
543
+ last_modification_date = DateTimeStamp(result["knora-api:lastModificationDate"])
544
+ return last_modification_date, ResourceClass.fromJsonObj(self._con, self._context, result["@graph"])
545
+
546
+ def update(self, last_modification_date: DateTimeStamp) -> tuple[DateTimeStamp, ResourceClass]:
547
+ #
548
+ # Note: DSP is able to change only one thing per call, either label or comment!
549
+ #
550
+ result = None
551
+ something_changed = False
552
+ if "label" in self._changed:
553
+ jsonobj = self._toJsonObj_update(last_modification_date, "label")
554
+ result = self._con.put(ResourceClass.ROUTE, jsonobj)
555
+ last_modification_date = DateTimeStamp(result["knora-api:lastModificationDate"])
556
+ something_changed = True
557
+ if "comment" in self._changed:
558
+ jsonobj = self._toJsonObj_update(last_modification_date, "comment")
559
+ result = self._con.put(ResourceClass.ROUTE, jsonobj)
560
+ last_modification_date = DateTimeStamp(result["knora-api:lastModificationDate"])
561
+ something_changed = True
562
+ if something_changed:
563
+ return last_modification_date, ResourceClass.fromJsonObj(self._con, self._context, result["@graph"])
564
+ else:
565
+ return last_modification_date, self
566
+
567
+ def _toJsonObj_update(self, lastModificationDate: DateTimeStamp, what_changed: str) -> dict[str, Any]:
568
+ ontid, resid = self._get_onto_res_iri()
569
+ tmp = {
570
+ "@id": ontid, # self._ontology_id,
571
+ "@type": "owl:Ontology",
572
+ "knora-api:lastModificationDate": lastModificationDate.toJsonObj(),
573
+ "@graph": [
574
+ {
575
+ "@id": resid,
576
+ "@type": "owl:Class",
577
+ }
578
+ ],
579
+ "@context": self._context.toJsonObj(),
580
+ }
581
+ if what_changed == "label":
582
+ if not self._label.isEmpty() and "label" in self._changed:
583
+ tmp["@graph"][0]["rdfs:label"] = self._label.toJsonLdObj()
584
+ if what_changed == "comment":
585
+ if not self._comment.isEmpty() and "comment" in self._changed:
586
+ tmp["@graph"][0]["rdfs:comment"] = self._comment.toJsonLdObj()
587
+ return tmp
588
+
589
+ def _toJsonObj_create(self, lastModificationDate: DateTimeStamp) -> dict[str, Any]:
590
+ ontid, resid = self._get_onto_res_iri()
591
+ if self._name is None:
592
+ raise BaseError("There must be a valid resource class name!")
593
+ if self._ontology_id is None:
594
+ raise BaseError("There must be a valid ontology_id given!")
595
+ if self._superclasses is None:
596
+ superclasses = [{"@id": "knora-api:Resource"}]
597
+ else:
598
+ superclasses = list(map(self._resolve_resref, self._superclasses))
599
+ if self._label is None or self._label.isEmpty():
600
+ self._label = LangString("no label available")
601
+ tmp = {
602
+ "@id": ontid, # self._ontology_id,
603
+ "@type": "owl:Ontology",
604
+ "knora-api:lastModificationDate": lastModificationDate.toJsonObj(),
605
+ "@graph": [
606
+ {
607
+ "@id": resid,
608
+ "@type": "owl:Class",
609
+ "rdfs:label": self._label.toJsonLdObj(),
610
+ "rdfs:subClassOf": superclasses,
611
+ }
612
+ ],
613
+ "@context": self._context.toJsonObj(),
614
+ }
615
+ if self._comment:
616
+ tmp["@graph"][0]["rdfs:comment"] = self._comment.toJsonLdObj()
617
+ return tmp
618
+
619
+ def _get_onto_res_iri(self) -> tuple[str, str]:
620
+ exp = regex.compile("^http.*") # It is already a fully IRI
621
+ if exp.match(self._ontology_id):
622
+ resid = self._context.prefix_from_iri(self._ontology_id) + ":" + self._name
623
+ ontid = self._ontology_id
624
+ else:
625
+ resid = self._ontology_id + ":" + self._name
626
+ ontid = self._context.iri_from_prefix(self._ontology_id)
627
+ return ontid, resid
628
+
629
+ def _resolve_resref(self, resref: str) -> dict[str, str]:
630
+ tmp = resref.split(":")
631
+ if len(tmp) > 1:
632
+ if tmp[0] and self._context.iri_from_prefix(tmp[0]) != self._ontology_id:
633
+ self._context.add_context(tmp[0])
634
+ return {"@id": resref} # fully qualified name in the form "prefix:name"
635
+ else:
636
+ return {
637
+ "@id": self._context.prefix_from_iri(self._ontology_id) + ":" + tmp[1]
638
+ } # ":name" in current ontology
639
+ else:
640
+ return {"@id": "knora-api:" + resref} # no ":", must be from knora-api!
641
+
642
+ def createDefinitionFileObj(self, context: Context, shortname: str, skiplist: list[str]) -> dict[str, Any]:
643
+ resource = {"name": self._name}
644
+ if self._superclasses:
645
+ resource["super"] = self._create_DefinitionFileObj_superclass(context, shortname)
646
+ resource["labels"] = self._label.createDefinitionFileObj()
647
+ if not self._comment.isEmpty():
648
+ resource["comments"] = self._comment.createDefinitionFileObj()
649
+ if self._has_properties:
650
+ self._create_DefinitionFileObj_cardinalities(context, resource, shortname, skiplist)
651
+ return resource
652
+
653
+ def _create_DefinitionFileObj_cardinalities(
654
+ self, context: Context, resource: dict[str, str], shortname: str, skiplist: list[str]
655
+ ) -> dict[str, Any]:
656
+ cardinalities: list[dict[str, Any]] = []
657
+ for _, hp in self._has_properties.items():
658
+ if hp.property_id in skiplist:
659
+ continue
660
+ if hp.ptype == HasProperty.Ptype.other or hp.property_id in [
661
+ "knora-api:isPartOf",
662
+ "knora-api:seqnum",
663
+ ]:
664
+ cardinalities.append(hp.createDefinitionFileObj(context, shortname))
665
+ if cardinalities:
666
+ resource["cardinalities"] = cardinalities
667
+ return resource
668
+
669
+ def _create_DefinitionFileObj_superclass(self, context: Context, shortname: str) -> list[str] | str:
670
+ if len(self._superclasses) > 1:
671
+ superclasses = []
672
+ for sc in self._superclasses:
673
+ superclasses.append(context.reduce_iri(sc, shortname))
674
+ else:
675
+ superclasses = context.reduce_iri(self._superclasses[0], shortname)
676
+ return superclasses