Warning:
This wiki has been archived and is now read-only.
Primary Keys with URI Pattern
In many scenarios a class has a primary key - one of its properties that uniquely identifies instances of that class. For example, ex:ISOCountry would have primary key ex:code. Furthermore, it is often useful to have a mapping between those property values and the URI of that instance. For example, if you have an instance with
ex:code "de" .
then the URI of that instance should be <http://example.org/Country-de> based on a URI start of "http://example.org/Country-".
This information is useful on many levels:
- When importing data from databases or spreadsheets, suitable URIs can be created for each row
- When someone creates a new instance, the UI can force her to enter a primary key, make sure it's unique and directly create a suitable URI
- a URI pattern makes sure that no duplicate instances exist
- primary keys can be handled with a special life cycle, e.g. a UI can prevent changing primary key values once they are in production.
This is an example of information that is both a constraint check and structural metadata.
An example representation of this using a SPIN template is
ex:ISOCountry a owl:Class ; spin:constraint [ a spl:PrimaryKeyPropertyConstraint ; arg:property ex:code ; arg:uriStart "http://example.org/Country-" ] ...
Applications can query this structural metadata without a SPIN engine or knowledge of SPARQL. They only need to agree on the URI (here: spl:PrimaryKeyPropertyConstraint).
The SPIN template above can be represented as
spl:PrimaryKeyPropertyConstraint a spl:ConstraintTemplate ; rdfs:comment """ Specifies that the given property is a primary key for instances of the associated class (and its subclasses). If a property has been declared to be the primary key then each instance of the class must have exactly one value for that property. Furthermore, the URIs of those instances must start with a given string (arg:uriStart), followed by the URL-encoded primary key value. For example if arg:uriStart is \"http://example.org/country-\" and the primary key for an instance is \"de\" then the URI must be \"http://example.org/country-de\". Finally, as a result of the URI policy, there can not be any other instance with the same value under the same primary key policy."""^^xsd:string ; rdfs:label "Primary key property constraint"^^xsd:string ; rdfs:subClassOf spl:PropertyConstraintTemplates ; spin:body [ a sp:Construct ; sp:text """ CONSTRUCT { _:cv a spin:ConstraintViolation ; rdfs:label ?label ; spin:violationRoot ?this ; spin:violationPath ?property . } WHERE { { FILTER NOT EXISTS { ?this ?property ?any . } . BIND (\"Missing value for primary key property\" AS ?label) . } UNION { FILTER (spl:objectCount(?this, ?property) > 1) . BIND (\"Multiple values of primary key property\" AS ?label) . } UNION { FILTER (spl:objectCount(?this, ?property) = 1) . ?this ?property ?value . BIND (CONCAT(?uriStart, ENCODE_FOR_URI(xsd:string(?value))) AS ?uri) . FILTER (xsd:string(?this) != ?uri) . BIND (CONCAT(\"Primary key value \", xsd:string(?value), \" does not align with the expected URI \", ?uri) AS ?label) . } . }"""^^xsd:string ] ; spin:constraint [ a spl:Argument ; rdfs:comment "The start of the URIs of well-formed instances of the associated class."^^xsd:string ; spl:predicate arg:uriStart ; spl:valueType xsd:string ] ; spin:labelTemplate "The property {?property} is the primary key and URIs start with {?uriStart}"^^xsd:string .
The constraint check above returns a different error message depending on the number of values of the primary key property. (The declaration of the argument arg:property is inherited from its superclass).
This requirement is related to R-2-UNIQUE-INSTANCES and owl:hasKey, but expands on those with the URI generation pattern.