Requirement: Primary keys with URI pattern

(This is a proposal for the requirements catalog)

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 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.

Regards,
Holger

Received on Wednesday, 22 October 2014 23:05:06 UTC