diff --git a/docs/api/crud/read.rst b/docs/api/crud/read.rst index 15dcec1..9e0e87d 100644 --- a/docs/api/crud/read.rst +++ b/docs/api/crud/read.rst @@ -36,12 +36,12 @@ Handling imports ================ Cowl delegates locating and loading imported ontologies to the end user via the -:struct:`CowlImportLoader` interface. Import loaders can be either provided locally -to specific objects (such as via :func:`cowl_manager_set_import_loader()`), -or you can opt to specify a global import loader via :func:`cowl_set_import_loader`. -If you do both, Cowl prioritizes local loaders, as you would expect. +:struct:`CowlImportResolver` interface. Import resolvers can be provided to :struct:`CowlManager` +instances via :func:`cowl_manager_set_import_resolver()`. By default, :struct:`CowlManager` will +attempt to resolve imports based on the IRIs of ontologies it is currently responsible for, +i.e. those that have been loaded or created through it. -.. doxygenstruct:: CowlImportLoader +.. doxygenstruct:: CowlImportResolver .. _istream: diff --git a/examples/01_errors_imports.c b/examples/01_errors_imports.c index 3ba1441..3903cca 100644 --- a/examples/01_errors_imports.c +++ b/examples/01_errors_imports.c @@ -23,16 +23,9 @@ * the imported ontology from the local filesystem. In this example * we just return a generic local "import.owl" ontology, disregarding its IRI. */ -static CowlOntology *load_import(cowl_unused void *ctx, cowl_unused CowlIRI *iri) { - CowlOntology *import = NULL; - CowlManager *manager = cowl_manager(); - - if (manager) { - import = cowl_manager_read_path(manager, ustring_literal(IMPORT)); - cowl_release(manager); - } - - return import; +static CowlOntology *resolve_import(void *ctx, cowl_unused CowlIRI *iri) { + // In this example, the manager is passed as the resolver's context. + return cowl_manager_read_path(ctx, ustring_literal(IMPORT)); } /* @@ -51,10 +44,7 @@ int main(void) { return EXIT_FAILURE; } - // Setup a global error handler and import loader. - CowlImportLoader loader = { NULL, load_import }; - cowl_set_import_loader(loader); - + // Setup a global error handler. UOStream stream; if (uostream_to_path(&stream, LOG)) { fprintf(stderr, "Failed to open " LOG "\n"); @@ -64,13 +54,21 @@ int main(void) { CowlErrorHandler handler = { &stream, handle_error }; cowl_set_error_handler(handler); - // Read the ontology from file. CowlManager *manager = cowl_manager(); if (!manager) { return EXIT_FAILURE; } + // Setup a custom import resolver. + // + // Note that the manager will already attempt to resolve imports based on the + // IRIs of ontologies it is currently responsible for. A custom resolver is only + // needed if you need to override this behavior. + CowlImportResolver resolver = { manager, resolve_import }; + cowl_manager_set_import_resolver(manager, resolver); + + // Read the ontology from file. CowlOntology *onto = cowl_manager_read_path(manager, ustring_literal(ONTO)); if (!onto) { diff --git a/include/cowl.h b/include/cowl.h index c0de460..49d71be 100644 --- a/include/cowl.h +++ b/include/cowl.h @@ -60,7 +60,7 @@ #include "cowl_facet_restr.h" #include "cowl_func_data_prop_axiom.h" #include "cowl_has_key_axiom.h" -#include "cowl_import_loader.h" +#include "cowl_import_resolver.h" #include "cowl_individual.h" #include "cowl_inv_obj_prop.h" #include "cowl_inv_obj_prop_axiom.h" diff --git a/include/cowl_config.h b/include/cowl_config.h index 181e1c3..aac16bc 100644 --- a/include/cowl_config.h +++ b/include/cowl_config.h @@ -15,7 +15,6 @@ #include "cowl_attrs.h" #include "cowl_error_handler.h" -#include "cowl_import_loader.h" #include "cowl_reader.h" #include "cowl_ret.h" #include "cowl_writer.h" @@ -108,24 +107,6 @@ CowlErrorHandler cowl_get_error_handler(void); COWL_API void cowl_set_error_handler(CowlErrorHandler handler); -/** - * Gets the global import loader. - * - * @return The global import loader. - */ -COWL_API -CowlImportLoader cowl_get_import_loader(void); - -/** - * Sets the global import loader. - * - * @param loader The import loader. - * - * @note This function must be called again if you reinitialize the library after deinitializing it. - */ -COWL_API -void cowl_set_import_loader(CowlImportLoader loader); - /// @} COWL_END_DECLS diff --git a/include/cowl_import_loader.h b/include/cowl_import_loader.h deleted file mode 100644 index 6226340..0000000 --- a/include/cowl_import_loader.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Defines CowlImportLoader and declares its API. - * - * @author Ivano Bilenchi - * - * @copyright Copyright (c) 2019 SisInf Lab, Polytechnic University of Bari - * @copyright - * @copyright SPDX-License-Identifier: EPL-2.0 - * - * @file - */ - -#ifndef COWL_IMPORT_LOADER_H -#define COWL_IMPORT_LOADER_H - -#include "cowl_attrs.h" -#include "cowl_error.h" -#include "cowl_macros.h" - -COWL_BEGIN_DECLS - -/// @cond -cowl_struct_decl(CowlIRI); -cowl_struct_decl(CowlOntology); -/// @endcond - -/** - * Provides a mechanism for generic handling of [ontology imports]. - * - * The `load_ontology` function should return the ontology that has the specified @type{#CowlIRI}. - * Imports retrieval and loading is deliberately left to the implementor. - * - * [ontology imports]: https://www.w3.org/TR/owl2-syntax/#Imports - */ -typedef struct CowlImportLoader { - - /// Loader context, can be anything. - void *ctx; - - /** - * Pointer to a function that returns the ontology having the specified IRI. - * - * @param ctx Loader context. - * @param iri IRI of the ontology to load. - * @return The imported ontology, or NULL on error. - */ - CowlOntology *(*load_ontology)(void *ctx, CowlIRI *iri); - - /** - * Pointer to a resource deallocator function for the context. - * - * @param ctx Loader context. - * - * @note Can be NULL if the context does not need to release resources. - */ - void (*free)(void *ctx); - -} CowlImportLoader; - -COWL_END_DECLS - -#endif // COWL_IMPORT_LOADER_H diff --git a/include/cowl_import_resolver.h b/include/cowl_import_resolver.h new file mode 100644 index 0000000..340cc03 --- /dev/null +++ b/include/cowl_import_resolver.h @@ -0,0 +1,90 @@ +/** + * Defines CowlImportResolver and declares its API. + * + * @author Ivano Bilenchi + * + * @copyright Copyright (c) 2024 SisInf Lab, Polytechnic University of Bari + * @copyright + * @copyright SPDX-License-Identifier: EPL-2.0 + * + * @file + */ + +#ifndef COWL_IMPORT_RESOLVER_H +#define COWL_IMPORT_RESOLVER_H + +#include "cowl_attrs.h" +#include "cowl_macros.h" + +COWL_BEGIN_DECLS + +/// @cond +cowl_struct_decl(CowlIRI); +cowl_struct_decl(CowlManager); +cowl_struct_decl(CowlOntology); +/// @endcond + +/** + * Provides a mechanism for generic handling of [ontology imports]. + * + * The `resolve_import` function should return the ontology associated to the specified + * @type{#CowlIRI}. Imports retrieval and loading is deliberately left to the implementor. + * + * [ontology imports]: https://www.w3.org/TR/owl2-syntax/#Imports + */ +typedef struct CowlImportResolver { + + /// Resolver context, can be anything. + void *ctx; + + /** + * Pointer to a function that returns the ontology associated to the specified IRI. + * + * @param ctx Resolver context. + * @param iri The IRI. + * @return Imported ontology, or NULL on error. + * + * @note The returned ontology must be retained. + */ + CowlOntology *(*resolve_import)(void *ctx, CowlIRI *iri); + + /** + * Pointer to a resource deallocator function. + * + * @param ctx Resolver context. + * + * @note Can be NULL if the resolver does not need to release resources. + */ + void (*free)(void *ctx); + +} CowlImportResolver; + +/** + * Returns the ontology associated to the specified IRI. + * + * @param resolver The resolver. + * @param iri The IRI. + * @return Imported ontology, or NULL on error. + */ +COWL_RETAINED +COWL_INLINE +CowlOntology * +cowl_import_resolver_resolve_import(CowlImportResolver const *resolver, CowlIRI *iri) { + return resolver->resolve_import(resolver->ctx, iri); +} + +/** + * Default import resolver, which looks for the ontology with the specified IRI + * in the manager's ontologies. + * + * @param manager The manager. + * @return Default import resolver. + * + * @note The manager is set as the resolver context, but it is not retained. + */ +COWL_API +CowlImportResolver cowl_import_resolver_default(CowlManager *manager); + +COWL_END_DECLS + +#endif // COWL_IMPORT_RESOLVER_H diff --git a/include/cowl_manager.h b/include/cowl_manager.h index de56681..144924d 100644 --- a/include/cowl_manager.h +++ b/include/cowl_manager.h @@ -15,7 +15,7 @@ #include "cowl_attrs.h" #include "cowl_error_handler.h" -#include "cowl_import_loader.h" +#include "cowl_import_resolver.h" #include "cowl_istream_handlers.h" #include "cowl_iterator.h" #include "cowl_macros.h" @@ -95,22 +95,22 @@ COWL_API void cowl_manager_set_writer(CowlManager *manager, CowlWriter writer); /** - * Gets the import loader. + * Gets the import resolver. * * @param manager The manager. - * @return The import loader. + * @return The import resolver. */ COWL_API -CowlImportLoader cowl_manager_get_import_loader(CowlManager *manager); +CowlImportResolver cowl_manager_get_import_resolver(CowlManager *manager); /** - * Sets the import loader. + * Sets the import resolver. * * @param manager The manager. - * @param loader The import loader. + * @param resolver The import resolver. */ COWL_API -void cowl_manager_set_import_loader(CowlManager *manager, CowlImportLoader loader); +void cowl_manager_set_import_resolver(CowlManager *manager, CowlImportResolver resolver); /** * Gets the error handler. diff --git a/include/cowl_ontology.h b/include/cowl_ontology.h index 0908c51..12621c0 100644 --- a/include/cowl_ontology.h +++ b/include/cowl_ontology.h @@ -17,6 +17,7 @@ #include "cowl_attrs.h" #include "cowl_axiom_flags.h" #include "cowl_axiom_type.h" +#include "cowl_import_resolver.h" #include "cowl_iterator.h" #include "cowl_macros.h" #include "cowl_position.h" @@ -140,26 +141,15 @@ COWL_API bool cowl_ontology_remove_annot(CowlOntology *onto, CowlAnnotation *annot); /** - * Gets an imported ontology given its import IRI. + * Checks if the given ontology has an import with the specified IRI. * * @param onto The ontology. - * @param iri Import IRI. - * @return Imported ontology. - */ -COWL_API -COWL_PURE -CowlOntology *cowl_ontology_get_import(CowlOntology *onto, CowlIRI *iri); - -/** - * Gets the import IRI of an imported ontology. - * - * @param onto The ontology. - * @param import The imported ontology. - * @return Import IRI. + * @param import IRI of the imported ontology. + * @return True if the ontology has the specified import, false otherwise. */ COWL_API COWL_PURE -CowlIRI *cowl_ontology_get_import_iri(CowlOntology *onto, CowlOntology *import); +bool cowl_ontology_has_import(CowlOntology *onto, CowlIRI *import); /** * Adds an import to the ontology. diff --git a/src/cowl_config.c b/src/cowl_config.c index 87b0dfb..3b86302 100644 --- a/src/cowl_config.c +++ b/src/cowl_config.c @@ -12,7 +12,6 @@ #include "cowl_anon_ind_private.h" #include "cowl_entity_private.h" #include "cowl_error_handler.h" -#include "cowl_import_loader.h" #include "cowl_iri_private.h" #include "cowl_reader.h" #include "cowl_ret.h" @@ -23,7 +22,6 @@ static bool cowl_initialized = false; static CowlErrorHandler global_error_handler; -static CowlImportLoader global_import_loader; static CowlReader global_reader; static CowlWriter global_writer; @@ -41,7 +39,6 @@ static CowlWriter global_writer; static void cowl_config_init(void) { global_error_handler = (CowlErrorHandler){ 0 }; - global_import_loader = (CowlImportLoader){ 0 }; global_reader = cowl_default_reader(); global_writer = cowl_default_writer(); @@ -51,7 +48,6 @@ static void cowl_config_init(void) { static void cowl_config_deinit(void) { if (global_error_handler.free) global_error_handler.free(global_error_handler.ctx); - if (global_import_loader.free) global_import_loader.free(global_import_loader.ctx); } cowl_ret cowl_init(void) { @@ -89,17 +85,6 @@ void cowl_set_error_handler(CowlErrorHandler handler) { global_error_handler = handler; } -CowlImportLoader cowl_get_import_loader(void) { - return (CowlImportLoader){ - .ctx = global_import_loader.ctx, - .load_ontology = global_import_loader.load_ontology, - }; -} - -void cowl_set_import_loader(CowlImportLoader loader) { - global_import_loader = loader; -} - CowlReader cowl_get_reader(void) { return global_reader; } diff --git a/src/cowl_import_resolver.c b/src/cowl_import_resolver.c new file mode 100644 index 0000000..106eb8a --- /dev/null +++ b/src/cowl_import_resolver.c @@ -0,0 +1,26 @@ +/** + * @author Ivano Bilenchi + * + * @copyright Copyright (c) 2019 SisInf Lab, Polytechnic University of Bari + * @copyright + * @copyright SPDX-License-Identifier: EPL-2.0 + * + * @file + */ + +#include "cowl_import_resolver.h" +#include "cowl_manager.h" +#include "cowl_object.h" +#include + +static CowlOntology *default_resolve_import(void *ctx, CowlIRI *iri) { + CowlOntology *onto = cowl_manager_retrieve_ontology(ctx, iri, NULL); + return onto ? cowl_retain(onto) : NULL; +} + +CowlImportResolver cowl_import_resolver_default(CowlManager *manager) { + return (CowlImportResolver){ + .ctx = manager, + .resolve_import = default_resolve_import, + }; +} diff --git a/src/cowl_manager.c b/src/cowl_manager.c index 287396e..926f9a5 100644 --- a/src/cowl_manager.c +++ b/src/cowl_manager.c @@ -11,7 +11,7 @@ #include "cowl_any.h" #include "cowl_config.h" #include "cowl_error_handler.h" -#include "cowl_import_loader.h" +#include "cowl_import_resolver.h" #include "cowl_istream.h" #include "cowl_istream_handlers.h" #include "cowl_istream_private.h" @@ -38,12 +38,13 @@ CowlManager *cowl_manager(void) { *manager = (CowlManager){ .super = COWL_OBJECT_INIT(COWL_OT_MANAGER), .ontos = uvec(CowlObjectPtr), + .resolver = cowl_import_resolver_default(manager), }; return manager; } void cowl_manager_free(CowlManager *manager) { - if (manager->loader.free) manager->loader.free(manager->loader.ctx); + if (manager->resolver.free) manager->resolver.free(manager->resolver.ctx); if (manager->handler.free) manager->handler.free(manager->handler.ctx); uvec_deinit(CowlObjectPtr, &manager->ontos); ulib_free(manager); @@ -61,8 +62,8 @@ CowlErrorHandler cowl_manager_get_error_handler(CowlManager *manager) { return manager->handler.handle_error ? manager->handler : cowl_get_error_handler(); } -CowlImportLoader cowl_manager_get_import_loader(CowlManager *manager) { - return manager->loader.load_ontology ? manager->loader : cowl_get_import_loader(); +CowlImportResolver cowl_manager_get_import_resolver(CowlManager *manager) { + return manager->resolver; } static CowlOntology *cowl_manager_read_stream_deinit(CowlManager *manager, UIStream *istream) { @@ -213,8 +214,9 @@ void cowl_manager_set_writer(CowlManager *manager, CowlWriter writer) { manager->writer = writer; } -void cowl_manager_set_import_loader(CowlManager *manager, CowlImportLoader loader) { - manager->loader = loader; +void cowl_manager_set_import_resolver(CowlManager *manager, CowlImportResolver resolver) { + if (!resolver.resolve_import) resolver = cowl_import_resolver_default(manager); + manager->resolver = resolver; } void cowl_manager_set_error_handler(CowlManager *manager, CowlErrorHandler handler) { diff --git a/src/cowl_manager_private.h b/src/cowl_manager_private.h index 3d925c6..4d204f7 100644 --- a/src/cowl_manager_private.h +++ b/src/cowl_manager_private.h @@ -13,7 +13,7 @@ #include "cowl_attrs.h" #include "cowl_error_handler.h" -#include "cowl_import_loader.h" +#include "cowl_import_resolver.h" #include "cowl_manager.h" // IWYU pragma: export #include "cowl_object_private.h" #include "cowl_reader.h" @@ -29,7 +29,7 @@ struct CowlManager { CowlReader reader; CowlWriter writer; CowlErrorHandler handler; - CowlImportLoader loader; + CowlImportResolver resolver; UVec(CowlObjectPtr) ontos; }; diff --git a/src/cowl_ontology.c b/src/cowl_ontology.c index b9fbdff..8cb7422 100644 --- a/src/cowl_ontology.c +++ b/src/cowl_ontology.c @@ -17,7 +17,7 @@ #include "cowl_axiom_type.h" #include "cowl_entity.h" #include "cowl_error_handler.h" -#include "cowl_import_loader.h" +#include "cowl_import_resolver.h" #include "cowl_iterator.h" #include "cowl_manager.h" #include "cowl_manager_private.h" @@ -38,16 +38,41 @@ #include "cowl_vector.h" #include "cowl_vector_private.h" #include "ulib.h" +#include #include -#define cowl_ontology_foreach_import(ONTO, IMPORT, CODE) \ - do { \ - cowl_table_foreach ((ONTO)->imports, p_##IMPORT##_var) { \ - if (!*p_##IMPORT##_var.val) continue; \ - CowlOntology *IMPORT = *p_##IMPORT##_var.val; \ - CODE; \ - } \ - } while (0) +typedef struct Imports_Loop { + CowlOntology *item; + ulib_uint i; + ulib_uint count; +} Imports_Loop; + +static inline ulib_uint imports_count(CowlOntology *onto) { + return onto->imports ? cowl_vector_count(onto->imports) : 0; +} + +static inline ulib_uint +next_import(CowlOntology *onto, ulib_uint i, ulib_uint count, CowlOntology **import) { + for (; i < count; ++i) { + CowlIRI *iri = cowl_vector_get_item(onto->imports, i); + *import = cowl_import_resolver_resolve_import(&onto->manager->resolver, iri); + if (*import) break; + } + return i; +} + +// clang-format off +#define foreach_import(ONTO, IMPORT) \ + for (Imports_Loop p_init_##IMPORT = { \ + .count = imports_count(ONTO) \ + }, \ + IMPORT = { \ + .count = p_init_##IMPORT.count, \ + .i = next_import(ONTO, 0, p_init_##IMPORT.count, &IMPORT.item) \ + }; \ + IMPORT.i < IMPORT.count; \ + IMPORT.i = next_import(ONTO, IMPORT.i + 1, IMPORT.count, &IMPORT.item)) +// clang-format on CowlOntology *cowl_ontology(CowlManager *manager) { CowlOntology *onto = ulib_alloc(onto); @@ -139,21 +164,23 @@ ulib_uint cowl_ontology_axiom_count(CowlOntology *onto, bool imports) { } if (imports) { - cowl_ontology_foreach_import(onto, import, { - count += cowl_ontology_axiom_count(import, true); - }); + foreach_import(onto, import) { + count += cowl_ontology_axiom_count(import.item, true); + cowl_release(import.item); + } } return count; } ulib_uint cowl_ontology_imports_count(CowlOntology *onto, bool imports) { - ulib_uint count = cowl_table_count(onto->imports); + ulib_uint count = cowl_vector_count(onto->imports); if (imports) { - cowl_ontology_foreach_import(onto, import, { - count += cowl_ontology_imports_count(import, true); - }); + foreach_import(onto, import) { + count += cowl_ontology_imports_count(import.item, true); + cowl_release(import.item); + } } return count; @@ -163,9 +190,10 @@ ulib_uint cowl_ontology_axiom_count_for_type(CowlOntology *onto, CowlAxiomType t ulib_uint count = cowl_vector_count(onto->axioms_by_type[type]); if (imports) { - cowl_ontology_foreach_import(onto, import, { - count += cowl_ontology_axiom_count_for_type(import, type, true); - }); + foreach_import(onto, import) { + count += cowl_ontology_axiom_count_for_type(import.item, type, true); + cowl_release(import.item); + } } return count; @@ -192,9 +220,10 @@ ulib_uint cowl_ontology_axiom_count_for_primitive(CowlOntology *onto, CowlAnyPri } if (imports) { - cowl_ontology_foreach_import(onto, import, { - count += cowl_ontology_axiom_count_for_primitive(import, primitive, true); - }); + foreach_import(onto, import) { + count += cowl_ontology_axiom_count_for_primitive(import.item, primitive, true); + cowl_release(import.item); + } } return count; @@ -211,9 +240,10 @@ cowl_ontology_primitives_count(CowlOntology *onto, CowlPrimitiveFlags flags, boo } if (imports) { - cowl_ontology_foreach_import(onto, import, { - count += cowl_ontology_primitives_count(import, flags, true); - }); + foreach_import(onto, import) { + count += cowl_ontology_primitives_count(import.item, flags, true); + cowl_release(import.item); + } } return count; @@ -229,9 +259,11 @@ bool cowl_ontology_has_primitive(CowlOntology *onto, CowlAnyPrimitive *primitive } if (imports) { - cowl_ontology_foreach_import(onto, import, { - if (cowl_ontology_has_primitive(import, primitive, true)) return true; - }); + foreach_import(onto, import) { + bool found = cowl_ontology_has_primitive(import.item, primitive, true); + cowl_release(import.item); + if (found) return true; + } } return false; @@ -242,9 +274,11 @@ bool cowl_ontology_has_axiom(CowlOntology *onto, CowlAnyAxiom *axiom, bool impor if (vec && cowl_vector_contains(vec, axiom)) return true; if (imports) { - cowl_ontology_foreach_import(onto, import, { - if (cowl_ontology_has_axiom(import, axiom, true)) return true; - }); + foreach_import(onto, import) { + bool found = cowl_ontology_has_axiom(import.item, axiom, true); + cowl_release(import.item); + if (found) return true; + } } return false; @@ -260,37 +294,45 @@ bool cowl_ontology_iterate_primitives(CowlOntology *onto, CowlPrimitiveFlags fla } if (imports) { - cowl_ontology_foreach_import(onto, import, { - if (!cowl_ontology_iterate_primitives(import, flags, iter, true)) return false; - }); + foreach_import(onto, import) { + bool next = cowl_ontology_iterate_primitives(import.item, flags, iter, true); + cowl_release(import.item); + if (!next) return false; + } } return true; } bool cowl_ontology_iterate_imports(CowlOntology *onto, CowlIterator *iter, bool imports) { - cowl_ontology_foreach_import(onto, import, { - if (!cowl_iterator_call(iter, import)) return false; - }); + foreach_import(onto, import) { + bool next = cowl_iterator_call(iter, import.item); + cowl_release(import.item); + if (!next) return false; + } if (imports) { - cowl_ontology_foreach_import(onto, import, { - if (!cowl_ontology_iterate_imports(import, iter, true)) return false; - }); + foreach_import(onto, import) { + bool next = cowl_ontology_iterate_imports(import.item, iter, true); + cowl_release(import.item); + if (!next) return false; + } } return true; } bool cowl_ontology_iterate_import_iris(CowlOntology *onto, CowlIterator *iter, bool imports) { - cowl_table_foreach (onto->imports, import) { - if (!cowl_iterator_call(iter, *import.key)) return false; + cowl_vector_foreach (onto->imports, import) { + if (!cowl_iterator_call(iter, *import.item)) return false; } if (imports) { - cowl_ontology_foreach_import(onto, import, { - if (!cowl_ontology_iterate_import_iris(import, iter, true)) return false; - }); + foreach_import(onto, import) { + bool next = cowl_ontology_iterate_import_iris(import.item, iter, true); + cowl_release(import.item); + if (!next) return false; + } } return true; @@ -304,9 +346,11 @@ bool cowl_ontology_iterate_axioms(CowlOntology *onto, CowlIterator *iter, bool i } if (imports) { - cowl_ontology_foreach_import(onto, import, { - if (!cowl_ontology_iterate_axioms(import, iter, true)) return false; - }); + foreach_import(onto, import) { + bool next = cowl_ontology_iterate_axioms(import.item, iter, true); + cowl_release(import.item); + if (!next) return false; + } } return true; @@ -319,9 +363,11 @@ bool cowl_ontology_iterate_axioms_of_type(CowlOntology *onto, CowlAxiomType type } if (imports) { - cowl_ontology_foreach_import(onto, import, { - if (!cowl_ontology_iterate_axioms_of_type(import, type, iter, true)) return false; - }); + foreach_import(onto, import) { + bool next = cowl_ontology_iterate_axioms_of_type(import.item, type, iter, true); + cowl_release(import.item); + if (!next) return false; + } } return true; @@ -352,11 +398,12 @@ bool cowl_ontology_iterate_axioms_for_primitive(CowlOntology *onto, CowlAnyPrimi } if (imports) { - cowl_ontology_foreach_import(onto, import, { - if (!cowl_ontology_iterate_axioms_for_primitive(import, primitive, iter, true)) { - return false; - } - }); + foreach_import(onto, import) { + bool next = cowl_ontology_iterate_axioms_for_primitive(import.item, primitive, iter, + true); + cowl_release(import.item); + if (!next) return false; + } } return true; } @@ -559,61 +606,23 @@ bool cowl_ontology_remove_annot(CowlOntology *onto, CowlAnnotation *annot) { return cowl_vector_remove(onto->annot, annot); } -CowlOntology *cowl_ontology_get_import(CowlOntology *onto, CowlIRI *iri) { - return onto->imports ? cowl_table_get_value(onto->imports, iri) : NULL; -} - -CowlIRI *cowl_ontology_get_import_iri(CowlOntology *onto, CowlOntology *import) { - if (!onto->imports) return NULL; - cowl_table_foreach (onto->imports, e) { - if (*e.val && cowl_ontology_equals(import, *e.val)) return *e.key; - } - return NULL; +bool cowl_ontology_has_import(CowlOntology *onto, CowlIRI *import) { + return onto->imports ? cowl_vector_contains(onto->imports, import) : false; } cowl_ret cowl_ontology_add_import(CowlOntology *onto, CowlIRI *import) { - ulib_uint idx = UHASH_INDEX_MISSING; - UHash(CowlObjectTable) map = uhmap_pi(CowlObjectTable, cowl_primitive_hash, - cowl_primitive_equals); - if (!onto->imports && !(onto->imports = cowl_table(&map))) goto err; - - UHash(CowlObjectTable) *tbl = &onto->imports->data; - uhash_ret hret = uhash_put(CowlObjectTable, tbl, import, &idx); - - if (hret == UHASH_INSERTED) { - cowl_retain(import); - } else if (hret == UHASH_PRESENT) { - return COWL_OK; - } else { - goto err; - } - - CowlOntology *import_onto = NULL; - CowlImportLoader loader = cowl_manager_get_import_loader(onto->manager); - if (loader.load_ontology && !(import_onto = loader.load_ontology(loader.ctx, import))) goto err; - uhash_value(CowlObjectTable, tbl, idx) = import_onto; - - return COWL_OK; - -err: - if (onto->imports && idx < uhash_size(CowlObjectTable, &onto->imports->data)) { - uhash_delete(CowlObjectTable, &onto->imports->data, idx); - } - cowl_handle_error_code(COWL_ERR_IMPORT, onto); - return COWL_ERR_IMPORT; + if (!onto->imports && !(onto->imports = cowl_vector_empty())) return COWL_ERR_MEM; + return cowl_vector_add(onto->imports, import); } bool cowl_ontology_remove_import(CowlOntology *onto, CowlIRI *iri) { if (!onto->imports) return false; - - UHash(CowlObjectTable) *tbl = &onto->imports->data; - ulib_uint idx = uhash_get(CowlObjectTable, tbl, iri); - if (idx == UHASH_INDEX_MISSING) return false; - - uhash_delete(CowlObjectTable, tbl, idx); - cowl_release(iri); - cowl_release(uhash_value(CowlObjectTable, tbl, idx)); - return true; + bool removed = cowl_vector_remove(onto->imports, iri); + if (removed && cowl_vector_count(onto->imports) == 0) { + cowl_release(onto->imports); + onto->imports = NULL; + } + return removed; } static inline cowl_ret diff --git a/src/cowl_ontology_private.h b/src/cowl_ontology_private.h index 8a003e4..48419d6 100644 --- a/src/cowl_ontology_private.h +++ b/src/cowl_ontology_private.h @@ -18,7 +18,7 @@ #include "cowl_ontology.h" // IWYU pragma: export #include "cowl_primitive_type.h" #include "cowl_ret.h" -#include "cowl_table.h" +#include "cowl_table.h" // IWYU pragma: keep, needed for UHash(CowlObjectTable) #include "cowl_vector.h" #include "ulib.h" @@ -32,7 +32,7 @@ struct CowlOntology { CowlIRI *version; CowlManager *manager; CowlSymTable *st; - CowlTable *imports; + CowlVector *imports; CowlVector *annot; CowlVector *axioms_by_type[COWL_AT_COUNT]; UHash(CowlObjectTable) refs[COWL_PT_COUNT]; diff --git a/test/tests/cowl_manager_tests.c b/test/tests/cowl_manager_tests.c index 9735c60..a616612 100644 --- a/test/tests/cowl_manager_tests.c +++ b/test/tests/cowl_manager_tests.c @@ -53,9 +53,7 @@ static cowl_ret count_axiom(void *ctx, cowl_unused CowlAnyAxiom *obj) { bool cowl_test_manager_read_ontology(void) { CowlManager *manager = cowl_manager(); utest_assert_not_null(manager); - - CowlImportLoader loader = { manager, cowl_test_load_import }; - cowl_manager_set_import_loader(manager, loader); + CowlOntology *import = cowl_manager_read_path(manager, ustring_literal(COWL_TEST_IMPORT)); ulib_uint count = 0; CowlIStreamHandlers handlers = { &count }; @@ -90,6 +88,9 @@ bool cowl_test_manager_read_ontology(void) { utest_assert_uint(ret, ==, COWL_OK); cowl_release(onto); + utest_assert_uint(cowl_manager_ontology_count(manager), ==, 1); + + cowl_release(import); utest_assert_uint(cowl_manager_ontology_count(manager), ==, 0); cowl_release_all(manager, stream); diff --git a/test/tests/cowl_ontology_tests.c b/test/tests/cowl_ontology_tests.c index b65d648..10ade6a 100644 --- a/test/tests/cowl_ontology_tests.c +++ b/test/tests/cowl_ontology_tests.c @@ -76,8 +76,7 @@ static void axiom_counts_by_type_init(void) { bool cowl_test_ontology_init(void) { axiom_counts_by_type_init(); CowlManager *manager = cowl_manager(); - CowlImportLoader loader = { manager, cowl_test_load_import }; - cowl_manager_set_import_loader(manager, loader); + cowl_manager_read_path(manager, ustring_literal(COWL_TEST_IMPORT)); onto = cowl_manager_read_path(manager, ustring_literal(COWL_TEST_ONTOLOGY)); cowl_release(manager); utest_assert_critical(onto); @@ -85,7 +84,8 @@ bool cowl_test_ontology_init(void) { } bool cowl_test_ontology_deinit(void) { - cowl_release(onto); + CowlIterator iter = cowl_iterator_release(); + cowl_manager_iterate_ontologies(cowl_ontology_get_manager(onto), &iter); return true; } diff --git a/test/tests/cowl_test_utils.c b/test/tests/cowl_test_utils.c deleted file mode 100644 index bb65341..0000000 --- a/test/tests/cowl_test_utils.c +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @author Ivano Bilenchi - * - * @copyright Copyright (c) 2019 SisInf Lab, Polytechnic University of Bari - * @copyright - * @copyright SPDX-License-Identifier: EPL-2.0 - * - * @file - */ - -#include "cowl_test_utils.h" -#include "cowl.h" -#include "ulib.h" - -// Import loader - -CowlOntology *cowl_test_load_import(void *ctx, cowl_unused CowlIRI *iri) { - return cowl_manager_read_path((CowlManager *)ctx, ustring_literal(COWL_TEST_IMPORT)); -} diff --git a/test/tests/cowl_test_utils.h b/test/tests/cowl_test_utils.h index 63ce301..9d9b765 100644 --- a/test/tests/cowl_test_utils.h +++ b/test/tests/cowl_test_utils.h @@ -51,8 +51,6 @@ uvec_decl(CowlError); #define COWL_TEST_ONTOLOGY "test_onto.owl" #define COWL_TEST_IMPORT "test_import.owl" -CowlOntology *cowl_test_load_import(void *ctx, CowlIRI *iri); - COWL_END_DECLS #endif // COWL_TEST_UTILS_H