Skip to content

feat(gen-owl): type a permissible value by the classes it instantiates - #31

Open
jdsika wants to merge 1 commit into
mainfrom
feat/owlgen-permissible-value-instantiates
Open

jdsika wants to merge 1 commit into
mainfrom
feat/owlgen-permissible-value-instantiates

Conversation

@jdsika

@jdsika jdsika commented Oct 2, 2026

Copy link
Copy Markdown

Summary

Fixes # — no issue covers this.

A permissible value can be an instance of a class defined in another schema: an open vocabulary declares the class (Category), and an extension contributes named individuals of it. The metamodel states exactly this with instantiates on the permissible value — "An element in another schema which this element instantiates" — but gen-owl ignored it. Its slot URI is linkml:instantiates, which add_metadata skips, so the individual was typed only with the enum's own class. A validator checking sh:class vocab:LicenseCategory then rejects the value, although the schema says it is one.

Each instantiates value of a permissible value with an IRI now becomes an rdf:type of that IRI:

enums:
  LinkCategory:
    implements: [owl:NamedIndividual]
    permissible_values:
      isLicense:
        meaning: ex:isLicense
        instantiates: [vocab:LicenseCategory]
ex:isLicense a owl:NamedIndividual, ex:LinkCategory, vocab:LicenseCategory .
ex:LinkCategory owl:oneOf ( ex:isLicense ... ) .
  • The enum still closes its own class with owl:oneOf; the instantiated class stays open, so other schemas can keep adding members.
  • Literal permissible values have no node to type, so instantiates is ignored with a warning, as meaning already is.

Without this, the only ways to type such individuals are a global --default-permissible-value-type (one class for every value of every enum) or an enum is_a, which must name another enum.

How was this tested?

  • New test_permissible_value_instantiates_types_the_value: single and multiple instantiates, the value keeps owl:NamedIndividual and the enum class, the enum's owl:oneOf is unchanged, a value without instantiates gets no extra type, and the instantiated class gets no owl:oneOf.
  • New test_permissible_value_instantiates_ignored_on_literal: no type triple and a warning.
  • pytest tests/linkml/test_generators/test_owlgen.py -m "not kroki" — 99 passed, 3 skipped.
  • ruff check and ruff format --check (0.11.13) clean.

Areas of uncertainty

  • Default owl:Class permissible values. A class value that instantiates a class is typed by it too, which is metaclass punning — the same reading instantiates has for classes elsewhere in the metamodel. Not restricted to individuals, because the metamodel does not restrict it.

Checklist

  • My code follows the contributor guidelines
  • I have added tests that prove my fix/feature works
  • Existing tests pass locally with my changes

AI Assistance

If you used AI tools while preparing this PR, you are still the author and responsible for understanding, verifying, and defending your submission. Please engage with reviewers personally rather than through your agent during feedback and revisions. See our AI Covenant for details.

A permissible value can be an instance of a class defined in another schema:
an open vocabulary declares the class, and an extension contributes named
individuals of it. The metamodel states this with `instantiates` on the
permissible value ("an element in another schema which this element
instantiates"), but gen-owl ignored it - its slot URI is linkml:instantiates,
which add_metadata skips - so the individual came out typed only with the
enum's own class. Validators checking `sh:class` against the open vocabulary
then rejected it.

Each `instantiates` value of a permissible value with an IRI now becomes an
rdf:type of that IRI. The enum still closes its own class with owl:oneOf; the
instantiated class stays open. On a permissible value rendered as a literal
there is nothing to type, so `instantiates` is ignored with a warning, as
`meaning` already is.

Signed-off-by: jdsika <carlo.van-driesten@vdl.digital>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant