Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Chapter 13: Talking to the Outside World

*The email from the Regional Veterinary Board was blunt:

Please submit your animal health records using the National Animal Health Ontology (NAHO) vocabulary. All concepts must use IRIs from http://naho.gov/ontology/. All species must reference the FAO species classification at http://fao.org/species/.

Dr. Portbridge looked at her Dolfin file. Her concepts were called Animal and Dog. The board expected http://naho.gov/ontology/Animal and http://fao.org/species/CanineDomestic. She needed a way to map her clean, readable names to the bureaucratic world of IRIs.


The problem

Dolfin ontologies live in a clean, human-readable world. The semantic web lives in a world of IRIs (Internationalized Resource Identifiers), long URLs that uniquely identify every concept, property, and individual. To interoperate, we need to connect the two.

Prefixes

A prefix declares a short alias for an IRI namespace:


prefix <http://naho.gov/ontology/> as naho
prefix <http://fao.org/species/> as fao

A prefix is only an alias for qualified references, naho.Animal expands to http://naho.gov/ontology/Animal. Declaring a prefix does not move your own concepts into that namespace. This:


prefix <http://naho.gov/ontology/> as naho

concept Animal:
  has name: one string

still defines Animal under your package’s own namespace. The naho prefix sits unused. To bind one of your concepts to an external IRI you must say so explicitly with @iri_name (see below).

Using prefixed references

Prefixes let you reference concepts from other ontologies:


prefix <http://schema.org/> as schema

concept Owner:
  has first_name: one string
  has last_name: one string
  has phone_numbers: at least 1 string
  has email: optional string
  has address: optional schema.PostalAddress

schema.PostalAddress refers to http://schema.org/PostalAddress, Schema.org’s definition of a postal address. You’re linking your clinic ontology to a globally recognized vocabulary.

The @iri_name annotation

This is how you actually bind a concept to an external IRI. The @iri_name annotation sits inside the concept body and takes the complete IRI in angle brackets. That IRI is used verbatim, it is not appended to your package namespace:


concept DomesticDog:
  @iri_name <http://fao.org/species/CanineDomestic>
  sub Animal
  has breed: optional string
  has neutered: one boolean

Here the local name DomesticDog stays clean and readable in your code, but the concept compiles to http://fao.org/species/CanineDomestic. Exactly the IRI the external system expects. This is what the board’s request required: local names mapped to bureaucratic IRIs. The annotation takes a full IRI in angle brackets only. A prefixed qualified name is not accepted here.

Multiple prefixes

A real-world ontology often bridges multiple external vocabularies:


prefix <http://naho.gov/ontology/> as naho
prefix <http://fao.org/species/> as fao
prefix <http://schema.org/> as schema
prefix <http://purl.org/dc/elements/1.1/> as dc

Each prefix is independent. You can use as many as needed.

The complete clinic with prefixes


prefix <http://naho.gov/ontology/> as naho
prefix <http://fao.org/species/> as fao
prefix <http://schema.org/> as schema

package <http://happypaws.com/clinic>:
  dolfin_version "1"
  version "1.0.0"
  author "Dr. Helen Portbridge"
  description "The Happy Paws veterinary clinic data model"

concept Species:
  one of:
    Dog
    Cat
    Bird
    Rabbit
    Reptile
    Other

concept Urgency:
  one of:
    Routine
    Urgent
    Emergency

concept AppointmentStatus:
  one of:
    Scheduled
    InProgress
    Completed
    Cancelled

concept Owner:
  has first_name: one string
  has last_name: one string
  has phone_numbers: at least 1 string
  has email: optional string
  has address: optional string
  has preferred_vet: optional Veterinarian

concept Veterinarian:
  has name: one string
  has license_number: one string
  has specialization: optional string

concept Surgeon:
  sub Veterinarian
  has surgery_count: one int
  has certified_procedures: at least 1 string

concept Dentist:
  sub Veterinarian
  has dental_certification: one string

concept Intern:
  sub Veterinarian
  has university: one string
  has year: one int

concept Vaccination:
  has vaccine_name: one string
  has date_administered: one string
  has batch_number: optional string

concept Animal:
  has name: one string
  has species: one Species
  has age: optional int
  has weight: optional float
  has owner: optional Owner
  has vaccinations: Vaccination
  has allergies: string

concept Dog:
  sub Animal
  has breed: optional string
  has neutered: one boolean

concept Cat:
  sub Animal
  has indoor: one boolean

concept Bird:
  sub Animal
  has wingspan: optional float
  has can_fly: one boolean

concept Appointment:
  has animal: one Animal
  has scheduled_for: one date_time
  has reason: one string
  has urgency: one Urgency
  has status: one AppointmentStatus
  has diagnosis: optional string
  has treatments: string
  has notes: optional string

property treatedBy: Animal -> Veterinarian

# Flag concepts and inference rules (Chapter 10)
concept UnvaccinatedAnimal
concept UnsafeAssignment
concept OverweightAnimal

rule flag_unvaccinated:
  match:
    ?animal a Animal
    ?animal vaccinations 0
  then:
    ?animal a UnvaccinatedAnimal

rule flag_intern_emergency:
  match:
    ?appt a Appointment
    ?appt urgency Emergency
    ?appt animal [ treatedBy [ a Intern ] ]
  then:
    ?appt a UnsafeAssignment

rule assign_primary_vet:
  match:
    ?animal a Animal
    ?animal owner [ preferred_vet ?vet ]
  then:
    ?animal treatedBy ?vet

# Unit-aware weight thresholds (Chapter 11)
concept OverweightCat

rule flag_overweight_dog:
  match:
    ?dog a Dog
    ?dog weight [ > quantity(40 kg) ]
  then:
    ?dog a OverweightAnimal

rule flag_overweight_cat:
  match:
    ?cat a Cat
    ?cat weight [ > quantity(6 kg) ]
  then:
    ?cat a OverweightCat

# Guard rails (Chapter 12)
concept SeniorCat
concept InvalidSurgery
concept UnderVaccinatedDog
concept AtRiskAnimal

rule flag_senior_cat:
  match:
    ?cat a Cat
    ?cat age [ >= 10 ]
  then:
    ?cat a SeniorCat

rule validate_surgery_staff:
  match:
    ?appt a Appointment
    ?appt reason "surgery"
    ?appt animal ?animal
    none ?vet:
      ?animal treatedBy ?vet
      ?vet a Surgeon
  then:
    ?appt a InvalidSurgery

rule check_dog_vaccines:
  match:
    ?dog a Dog
    ?dog vaccinations 0
  then:
    ?dog a UnderVaccinatedDog

rule flag_at_risk:
  match:
    ?animal a Animal
    ?animal age [ > 15 ]
    ?animal weight [ < quantity(2 kg) ]
    ?animal vaccinations 0
  then:
    ?animal a AtRiskAnimal

Try it

Add a prefix for Dublin Core (http://purl.org/dc/elements/1.1/) and FOAF (http://xmlns.com/foaf/0.1/):


prefix <http://naho.gov/ontology/> as naho

# Add Dublin Core and FOAF prefixes here

Dr. Portbridge submitted the data export. The board’s system accepted it without complaint, her concepts mapped cleanly to NAHO’s IRIs, and the species references aligned with FAO’s vocabulary. Her little clinic was speaking the same language as the national registry.

She leaned back in her chair and looked at the screen. What had started as a napkin sketch was now a complete data model: concepts with inheritance, cardinality constraints, enums for controlled vocabularies, rules for automated reasoning, constraints for validation, and prefixes for interoperability. Biscuit dozed at her feet. Pixel purred on the printer.