Skip to content

feat(contextgen): add @type: @vocab coercion for eligible enums#8

Open
jdsika wants to merge 1 commit intomainfrom
feat/contextgen-enum-vocab-coercion
Open

feat(contextgen): add @type: @vocab coercion for eligible enums#8
jdsika wants to merge 1 commit intomainfrom
feat/contextgen-enum-vocab-coercion

Conversation

@jdsika
Copy link
Copy Markdown

@jdsika jdsika commented Apr 24, 2026

Summary

Adds JSON-LD 1.1 @type: @vocab coercion for enum-ranged slots whose permissible values are eligible (all have meanings, single namespace, text matches local name).

Problem

LinkML's visit_enum is a no-op — enum permissible values are not emitted in the generated JSON-LD context. Slots with enum ranges only get a structural ENUM_CONTEXT mapping ({text: skos:notation, description: skos:prefLabel, meaning: @id}), which requires structured object values.

In practice, JSON data files use bare string enum values (e.g., "DrivableAreaType": "RoadTypeMotorway"). Without context support, these remain plain strings and don't expand to IRIs.

Upstream issue: linkml#2497

Approach

Uses JSON-LD 1.1 §4.2.3 (type coercion via @vocab) combined with §4.1.8 (scoped contexts):

"DrivableAreaType": {
  "@id": "openlabel_v2:DrivableAreaType",
  "@type": "@vocab",
  "@context": {
    "@vocab": "https://w3id.org/ascs-ev/envited-x/openlabel/v2/",
    "text": "skos:notation",
    "description": "skos:prefLabel",
    "meaning": "@id"
  }
}

This supports both value forms simultaneously:

  • Bare string: "RoadTypeMotorway" → expands to IRI via scoped @vocab
  • Structured object: {text, meaning} → SKOS mappings still work

Eligibility Criteria

An enum qualifies only when ALL conditions are met:

  1. Every permissible value has a meaning IRI
  2. All meaning IRIs share the same namespace prefix
  3. Each value's text matches the local part of its meaning CURIE

Ineligible enums fall back to the existing ENUM_CONTEXT behavior.

Changes

  • jsonldcontextgen.py: Added _vocab_eligible_enum() method + modified visit_slot enum branch
  • test_jsonldcontextgen.py: 7 new tests covering eligible/ineligible cases, pyld expansion verification, kitchen_sink fallback

Testing

  • All 38 context generator tests pass (35 passed + 3 xfailed)
  • All 77 OWL generator tests pass
  • pyld expansion tests verify correct IRI expansion for bare strings and structured objects
  • Kitchen sink schema correctly falls back (EmploymentEventType has text≠local)

References

@jdsika jdsika force-pushed the feat/contextgen-enum-vocab-coercion branch 2 times, most recently from 5cdcd02 to 63c5dd9 Compare April 24, 2026 19:29
Emit @type: @vocab with a scoped @vocab namespace for enum-ranged
slots whose permissible values all have meaning IRIs that share a
single namespace and whose text matches the meaning local name.

This enables bare string enum values (e.g. "RoadTypeMotorway") to
expand to full IRIs via JSON-LD 1.1 type coercion (section 4.2.3)
combined with scoped contexts (section 4.1.8).

The combined context preserves backward compatibility with structured
{text, description, meaning} objects via the existing SKOS mappings.

Enums that don't meet the eligibility criteria (missing meanings,
mixed namespaces, or text/local-name mismatches) fall back to the
existing ENUM_CONTEXT behavior.

Refs: linkml#2497
Signed-off-by: Carlo van Driesten <carlo.van-driesten@bmw.de>
@jdsika jdsika force-pushed the feat/contextgen-enum-vocab-coercion branch from 63c5dd9 to 5edfd2c Compare April 25, 2026 10:12
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