Examples
The following examples are designed to get you started using Cowl. They are ordered by complexity, so it is recommended that you read them sequentially.
Basic ontology parsing
1/*
2 * This introductory example shows how to read an ontology
3 * and log its axioms and annotations.
4 * Note that error and import handling are omitted for the sake of simplicity.
5 *
6 * @author Ivano Bilenchi
7 *
8 * @copyright Copyright (c) 2019 SisInf Lab, Polytechnic University of Bari
9 * @copyright <http://swot.sisinflab.poliba.it>
10 * @copyright SPDX-License-Identifier: EPL-2.0
11 */
12#include "cowl.h"
13
14#define ONTO "example_pizza.owl"
15
16int main(void) {
17 // You must always initialize the library before use.
18 cowl_init();
19
20 // Instantiate a manager and deserialize an ontology from file.
21 CowlManager *manager = cowl_manager();
22 CowlOntology *ontology = cowl_manager_read_path(manager, ustring_literal(ONTO));
23
24 if (ontology) {
25 // Do stuff with the ontology. In this case we are just logging it
26 // to the standard output using the default writer.
27 cowl_manager_write_file(manager, ontology, stdout);
28
29 // Release the ontology.
30 cowl_ontology_release(ontology);
31 }
32
33 // Release the manager.
34 cowl_manager_release(manager);
35
36 return EXIT_SUCCESS;
37}
Handling of errors and imports
1/*
2 * This example is the same as the previous one,
3 * except error and import handling are included.
4 *
5 * @author Ivano Bilenchi
6 *
7 * @copyright Copyright (c) 2019 SisInf Lab, Polytechnic University of Bari
8 * @copyright <http://swot.sisinflab.poliba.it>
9 * @copyright SPDX-License-Identifier: EPL-2.0
10 */
11#include "cowl.h"
12
13#define ONTO "example_pizza.owl"
14#define IMPORT "import.owl"
15#define LOG "errors.log"
16
17static CowlOntology *load_import(void *ctx, CowlIRI *iri);
18static void handle_error(void *ctx, CowlError const *error);
19
20int main(void) {
21
22 // API initialization can fail due to low memory.
23 if (cowl_init()) {
24 return EXIT_FAILURE;
25 }
26
27 // Setup a global error handler and import loader.
28 CowlImportLoader loader = { NULL, load_import };
29 cowl_set_import_loader(loader);
30
31 UOStream stream;
32 if (uostream_to_path(&stream, LOG)) {
33 return EXIT_FAILURE;
34 }
35
36 CowlErrorHandler handler = { &stream, handle_error };
37 cowl_set_error_handler(handler);
38
39 // Read the ontology from file.
40 CowlManager *manager = cowl_manager();
41
42 if (manager) {
43 CowlOntology *onto = cowl_manager_read_path(manager, ustring_literal(ONTO));
44
45 // Do stuff with the ontology.
46 if (onto) {
47 cowl_manager_write_file(manager, onto, stdout);
48 cowl_ontology_release(onto);
49 }
50
51 cowl_manager_release(manager);
52 }
53
54 uostream_deinit(&stream);
55
56 return EXIT_SUCCESS;
57}
58
59/*
60 * You should return the appropriate ontology given the specified IRI.
61 * This may involve making network requests or simply retrieving
62 * the imported ontology from the local filesystem. In this example
63 * we just return a generic local "import.owl" ontology, disregarding its IRI.
64 */
65static CowlOntology *load_import(cowl_unused void *ctx, cowl_unused CowlIRI *iri) {
66 CowlOntology *import = NULL;
67 CowlManager *manager = cowl_manager();
68
69 if (manager) {
70 import = cowl_manager_read_path(manager, ustring_literal(IMPORT));
71 cowl_manager_release(manager);
72 }
73
74 return import;
75}
76
77/*
78 * In general, it is very reasonable to just check that the ontology returned
79 * by the manager is not NULL. The error handler mechanism is only needed if you wish
80 * to implement more fine-grained error handling. In this example, errors are logged.
81 */
82static void handle_error(void *ctx, CowlError const *error) {
83 cowl_write_error(ctx, error);
84}
Ontology querying
1/*
2 * In this example we will be logging the direct atomic subclasses
3 * of a certain class. Note that error and import handling are omitted
4 * for the sake of simplicity.
5 *
6 * @author Ivano Bilenchi
7 *
8 * @copyright Copyright (c) 2019 SisInf Lab, Polytechnic University of Bari
9 * @copyright <http://swot.sisinflab.poliba.it>
10 * @copyright SPDX-License-Identifier: EPL-2.0
11 */
12#include "cowl.h"
13
14#define ONTO "example_pizza.owl"
15#define NS "http://www.co-ode.org/ontologies/pizza/pizza.owl#"
16#define CLASS_NAME "Food"
17
18// Iterator body, invoked for each class expression matching the query.
19static bool for_each_cls(cowl_unused void *ctx, CowlAny *cls) {
20 // We are only interested in atomic classes. Note that, due to pseudo-inheritance,
21 // this check ensures that the concrete type of 'exp' is CowlClass.
22 if (cowl_cls_exp_get_type(cls) != COWL_CET_CLASS) return true;
23
24 // Log the IRI remainder.
25 UOStream *std_out = uostream_std();
26 cowl_write_string(std_out, cowl_iri_get_rem(cowl_class_get_iri(cls)));
27 cowl_write_static(std_out, "\n");
28
29 return true;
30}
31
32int main(void) {
33 cowl_init();
34
35 CowlManager *manager = cowl_manager();
36 CowlOntology *ontology = cowl_manager_read_path(manager, ustring_literal(ONTO));
37 cowl_manager_release(manager);
38
39 // Query the ontology
40 if (ontology) {
41 // Get the class whose atomic subclasses we are interested in.
42 puts("Atomic subclasses of " CLASS_NAME ":");
43 CowlClass *cls = cowl_class_from_static(NS CLASS_NAME);
44
45 // Run the query.
46 CowlIterator iter = { NULL, for_each_cls };
47 cowl_ontology_iterate_sub_classes(ontology, cls, &iter, false);
48
49 // Cleanup.
50 cowl_class_release(cls);
51 cowl_ontology_release(ontology);
52 }
53
54 return EXIT_SUCCESS;
55}
Recursive ontology querying
1/*
2 * In this example we will be logging the atomic subclasses
3 * of a certain class recursively. Error and import handling are omitted.
4 *
5 * @author Ivano Bilenchi
6 *
7 * @copyright Copyright (c) 2019 SisInf Lab, Polytechnic University of Bari
8 * @copyright <http://swot.sisinflab.poliba.it>
9 * @copyright SPDX-License-Identifier: EPL-2.0
10 */
11#include "cowl.h"
12
13#define ONTO "example_pizza.owl"
14#define NS "http://www.co-ode.org/ontologies/pizza/pizza.owl#"
15#define CLASS_NAME "Food"
16
17// Iterator body, invoked for each class expression matching the query.
18static bool for_each_cls(void *ctx, CowlAny *cls) {
19 if (cowl_cls_exp_get_type(cls) != COWL_CET_CLASS) return true;
20
21 // Log the IRI remainder.
22 UOStream *std_out = uostream_std();
23 cowl_write_string(std_out, cowl_iri_get_rem(cowl_class_get_iri(cls)));
24 cowl_write_static(std_out, "\n");
25
26 // Recurse.
27 CowlIterator iter = { ctx, for_each_cls };
28 return cowl_ontology_iterate_sub_classes(ctx, cls, &iter, false);
29}
30
31int main(void) {
32 cowl_init();
33
34 CowlManager *manager = cowl_manager();
35 CowlOntology *ontology = cowl_manager_read_path(manager, ustring_literal(ONTO));
36 cowl_manager_release(manager);
37
38 if (ontology) {
39 puts("Recursive atomic subclasses of " CLASS_NAME ":");
40 CowlClass *cls = cowl_class_from_static(NS CLASS_NAME);
41
42 // Since we are going to perform a recursive query,
43 // we need the ontology to be part of the context.
44 CowlIterator iter = { ontology, for_each_cls };
45 cowl_ontology_iterate_sub_classes(ontology, cls, &iter, false);
46
47 cowl_class_release(cls);
48 cowl_ontology_release(ontology);
49 }
50
51 return EXIT_SUCCESS;
52}
Ontology editing and serialization
1/*
2 * This example demonstrates ontology editing and serialization to file.
3 * Error and import handling are deliberately omitted.
4 *
5 * @author Ivano Bilenchi
6 *
7 * @copyright Copyright (c) 2022 SisInf Lab, Polytechnic University of Bari
8 * @copyright <http://swot.sisinflab.poliba.it>
9 * @copyright SPDX-License-Identifier: EPL-2.0
10 */
11#include "cowl.h"
12
13#define IN_PATH "example_pizza.owl"
14#define OUT_PATH "example_pizza_new.owl"
15#define NS "http://www.co-ode.org/ontologies/pizza/pizza.owl#"
16
17int main(void) {
18 cowl_init();
19
20 // We will be editing the pizza ontology by adding a new type of pizza.
21 printf("Reading ontology " IN_PATH "...");
22 CowlManager *manager = cowl_manager();
23 CowlOntology *ontology = cowl_manager_read_path(manager, ustring_literal(IN_PATH));
24
25 if (ontology) {
26 printf(" done!\n");
27 } else {
28 printf(" failed\n");
29 return EXIT_FAILURE;
30 }
31
32 // Note that most of the following function calls can fail due to
33 // memory exhaustion, so you should always check their return values.
34 CowlClass *my_pizza = cowl_class_from_static(NS "MyPizza");
35 CowlClass *pizza = cowl_class_from_static(NS "Pizza");
36
37 // We first declare the new class.
38 CowlAnyAxiom *axiom = cowl_decl_axiom(my_pizza, NULL);
39 cowl_ontology_add_axiom(ontology, axiom);
40 cowl_decl_axiom_release(axiom);
41
42 // Then we state that it is a subclass of 'Pizza'.
43 axiom = cowl_sub_cls_axiom(my_pizza, pizza, NULL);
44 cowl_ontology_add_axiom(ontology, axiom);
45 cowl_sub_cls_axiom_release(axiom);
46
47 // Finally we serialize the edited ontology to a new file.
48 printf("Writing ontology " OUT_PATH "...");
49
50 if (cowl_manager_write_path(manager, ontology, ustring_literal(OUT_PATH))) {
51 printf(" failed\n");
52 } else {
53 printf(" done!\n");
54 }
55
56 cowl_release(my_pizza);
57 cowl_release(pizza);
58 cowl_release(ontology);
59 cowl_release(manager);
60
61 return EXIT_SUCCESS;
62}