Note

This page is work in progress.

Metadata Schema

Namespaces

When HELIPORT mints a Handle, the default suffix is derived from the namespace path and the database id of the object, for example namespace HELIPORT/documentation and pk 42 become HELIPORT.documentation.42 before prefixing by the Handle server prefix (see also heliport.core.models.DigitalObject.suffix_for_pid_generation() and heliport.core.pid_registration.handle_net).

This gives identifiers that are somewhat meaningful to humans while still being unique.

Main idea: namespaces are digital objects

In HELIPORT, a namespace is itself represented as a heliport.core.models.DigitalObject. This is in preparation for features that allow to own, manage and curate namespaces, but there are no such features implemented yet. Namespace digital objects themselves are, by default, created in the HELIPORT/namespace namespace. Assigning heliport.core.models.DigitalObject.namespace_str (a string like "HELIPORT/documentation") to an object does two things:

  • it assigns the object to a namespace path

  • it creates missing namespace nodes as digital objects

Each path segment is a digital object with:

  • rdf:type -> Namespace (whose PID is dcam:VocabularyEncodingScheme)

  • heliport:subNamespaceOf to its parent namespace node (except for the root)

The leaf namespace node (the last segment of the path) is also marked as a class:

  • rdf:type -> Class (whose PID is rdfs:Class)

This dual nature (namespace and class) is intentional: it keeps identifier namespaces and semantic typing aligned.

Vocabulary and IRIs used by namespace modeling

The core vocabulary objects are initialized in heliport.core.vocabulary_core. Important terms for namespace/class/property semantics are:

Graph structure (objects, classes, namespaces, properties)

At the metadata level, HELIPORT uses one graph model for everything namespace related: digital objects as nodes and semantic relations as edges.

Example how the namespace “HELIPORT/documentation” is represented:

# namespace hierarchy
:HELIPORT              rdf:type                    :Namespace
:documentation         rdf:type                    :Namespace
:documentation         rdf:type                    :Class
:documentation         heliport:subNamespaceOf     :HELIPORT

# suggested metadata properties for a namespace/class
:myProperty            dcam:domainIncludes         :documentation

# an instance object assigned to the namespace path
:doc_42                (namespace path)            HELIPORT/documentation

The last line is stored internally via namespace-path ids in heliport.core.models.DigitalObject.category and exposed via heliport.core.models.DigitalObject.namespace_str, rather than one dedicated RDF predicate. The semantic relations (type, subclass, subproperty, subnamespace, suggested property) are represented as normal heliport.core.models.DigitalObjectRelation entries. Selecting a namespace for a newly created digital object does currently not automatically assert an rdf:type relation on that object.

Operational flow in HELIPORT

  1. Namespace defaults are defined in settings (for example DOCUMENTATION_NAMESPACE = "HELIPORT/documentation" in heliport_config.settings).

  2. New objects are usually created with that namespace (for example using heliport.core.models.DigitalObject.save_with_namespace()).

  3. If namespace nodes are missing, they are created automatically as digital objects.

  4. In the Digital Objects UI, users can browse and edit the namespace tree and create new namespace/class nodes (see heliport.digital_objects.views, especially SaveCategoryView). For creating a new object in this UI, the final selected namespace must be a class (see src/heliport/digital_objects/static/digital_objects/object_form.js).

  5. On object creation, PID registration uses the namespace-derived suffix for Handle minting (see heliport.core.pid_registration.signal_handlers).

Special handling and conventions

  • Most app object types use fixed namespace constants from settings.

  • Projects use a structured dynamic namespace, including year and optionally group, e.g. HELIPORT/Projects/2026/MyGroup/Project (see heliport.core.utils.queries.create_empty_project()).

  • The historical term category is still present in parts of the code and API for compatibility, but conceptually this is the namespace used for PID naming.

Note

In some places, “namespaces” are referred to as “categories”. This is for legacy reasons only. We switched away from this term as to not suggest that type information (which could change for any given object) is part of the identifier.