diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2023-02-26 17:12:15 +0100 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2023-02-27 09:18:57 +0100 |
commit | f5af54d35ccc74552105940580767a63a856173b (patch) | |
tree | 4db18c08c03a36473ee591f2cc18430c3b0ca294 /docs | |
parent | 6842f5e904c1e6f6a4c6231e55ad49abf0d4c5a1 (diff) | |
download | tracker-f5af54d35ccc74552105940580767a63a856173b.tar.gz |
docs: Generate also diagrams for RDF class relationship
Highlight how do the various ontology classes relate to other classes.
Just like with the class diagrams, make things links so the documentation
can be navigated.
Diffstat (limited to 'docs')
-rw-r--r-- | docs/tools/tracker-docgen-md.c | 49 | ||||
-rw-r--r-- | docs/tools/tracker-utils.c | 88 |
2 files changed, 137 insertions, 0 deletions
diff --git a/docs/tools/tracker-docgen-md.c b/docs/tools/tracker-docgen-md.c index 8a1b82ecc..a43da208d 100644 --- a/docs/tools/tracker-docgen-md.c +++ b/docs/tools/tracker-docgen-md.c @@ -95,6 +95,54 @@ print_class_hierarchy (FILE *f, g_fprintf (f, "</div>\n"); } +static gboolean +check_range_non_literals (GList *properties, + TrackerOntologyModel *model) +{ + GList *l; + + for (l = properties; l; l = l->next) { + TrackerOntologyProperty *prop; + TrackerOntologyClass *domain; + + prop = tracker_ontology_model_get_property (model, l->data); + domain = tracker_ontology_model_get_class (model, prop->range->data); + + if (g_str_has_prefix (domain->shortname, "xsd:") || + g_str_equal (domain->shortname, "rdfs:Literal") || + g_str_equal (domain->shortname, "rdf:langString")) + continue; + + return TRUE; + } + + return FALSE; +} + +static void +print_rdf_diagram (FILE *f, + TrackerOntologyClass *klass, + TrackerOntologyModel *model) +{ + const gchar *id; + + if (!klass->in_range_of && + !check_range_non_literals (klass->in_domain_of, model)) + return; + + id = klass->shortname; + g_fprintf (f, "#### <a name=\"%s.hierarchy\"></a>RDF Diagram\n\n", id); + g_fprintf (f, "<div class=\"docblock\">\n"); + g_fprintf (f, + "<style>" + "svg .edge:hover a { text-decoration: none !important; fill: var(--primary); } " + "svg .edge:hover path { stroke: var(--primary); } " + "svg .edge:hover polygon { fill: var(--primary); stroke: var(--primary); }" + "</style>\n"); + g_fprintf (f, "{{ %s-diagram.svg }}\n", id); + g_fprintf (f, "</div>\n"); +} + static void print_flag (FILE *f, const gchar *flag_property_link, @@ -233,6 +281,7 @@ print_ontology_class (TrackerOntologyModel *model, } print_class_hierarchy (f, klass, model); + print_rdf_diagram (f, klass, model); if (klass->in_domain_of) { g_fprintf (f, "#### <a name=\"%s.properties\"></a>Properties\n\n", id); diff --git a/docs/tools/tracker-utils.c b/docs/tools/tracker-utils.c index 15eb5f448..5b7f7e686 100644 --- a/docs/tools/tracker-utils.c +++ b/docs/tools/tracker-utils.c @@ -502,6 +502,93 @@ ttl_generate_class_hierarchy_dot (TrackerOntologyDescription *description, fclose (f); } +static void +ttl_generate_rdf_diagram_dot (TrackerOntologyDescription *description, + TrackerOntologyModel *model, + TrackerOntologyClass *klass, + GFile *output_location) +{ + gchar *path, *filename; + GFile *file; + g_autoptr(GHashTable) visited = NULL; + g_autofree gchar *link = NULL; + FILE *f; + GList *l; + + if (!klass->subclasses && !klass->superclasses) + return; + + filename = g_strdup_printf ("%s-diagram.dot", klass->shortname); + file = g_file_get_child (output_location, filename); + g_free (filename); + + path = g_file_get_path (file); + f = fopen (path, "w"); + g_assert (f != NULL); + g_free (path); + + g_fprintf (f, "digraph G {\n"); + g_fprintf (f, "bgcolor=\"transparent\";\n"); + g_fprintf (f, "rankdir=LR;\n"); + + visited = g_hash_table_new (NULL, NULL); + describe_class (f, model, klass, FALSE); + + for (l = klass->in_domain_of; l; l = l->next) { + TrackerOntologyProperty *prop; + TrackerOntologyClass *range; + + prop = tracker_ontology_model_get_property (model, l->data); + range = tracker_ontology_model_get_class (model, prop->range->data); + + if (g_hash_table_contains (visited, prop)) + continue; + + if (g_str_has_prefix (range->shortname, "xsd:") || + g_str_equal (range->shortname, "rdfs:Literal") || + g_str_equal (range->shortname, "rdf:langString")) + continue; + + if (!g_hash_table_contains (visited, range)) { + describe_class (f, model, range, TRUE); + g_hash_table_add (visited, range); + } + + link = link_from_shortname (prop->shortname); + g_fprintf (f, "\"%s\" -> \"%s\" [label=\"%s\", fontname=\"sans-serif\", fontsize=10, href=\"%s\"]\n", + klass->shortname, range->shortname, prop->shortname, + link); + g_hash_table_add (visited, prop); + } + + for (l = klass->in_range_of; l; l = l->next) { + TrackerOntologyProperty *prop; + TrackerOntologyClass *domain; + + prop = tracker_ontology_model_get_property (model, l->data); + domain = tracker_ontology_model_get_class (model, prop->domain->data); + + if (g_hash_table_contains (visited, prop)) + continue; + + if (!g_hash_table_contains (visited, domain)) { + describe_class (f, model, domain, TRUE); + g_hash_table_add (visited, domain); + } + + link = link_from_shortname (prop->shortname); + g_fprintf (f, "\"%s\" -> \"%s\" [label=\"%s\", fontname=\"sans-serif\", fontsize=10, href=\"%s\"]\n", + domain->shortname, klass->shortname, prop->shortname, + link); + g_hash_table_add (visited, prop); + } + + g_fprintf (f, "}"); + + g_object_unref (file); + fclose (f); +} + void ttl_generate_dot_files (TrackerOntologyDescription *description, TrackerOntologyModel *model, @@ -519,5 +606,6 @@ ttl_generate_dot_files (TrackerOntologyDescription *description, klass = tracker_ontology_model_get_class (model, l->data); ttl_generate_class_hierarchy_dot (description, model, klass, output_location); + ttl_generate_rdf_diagram_dot (description, model, klass, output_location); } } |