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 athttp://fao.org/species/.Dr. Portbridge looked at her Dolfin file. Her concepts were called
AnimalandDog. The board expectedhttp://naho.gov/ontology/Animalandhttp://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.