summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2023-02-26 17:12:15 +0100
committerCarlos Garnacho <carlosg@gnome.org>2023-02-27 09:18:57 +0100
commitf5af54d35ccc74552105940580767a63a856173b (patch)
tree4db18c08c03a36473ee591f2cc18430c3b0ca294 /docs
parent6842f5e904c1e6f6a4c6231e55ad49abf0d4c5a1 (diff)
downloadtracker-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.c49
-rw-r--r--docs/tools/tracker-utils.c88
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);
}
}