This document is no longer maintained and is out of date. For the latest specification, see SHACL Specification.

LDOM (Linked Data Object Model) is an RDF-based modeling language that is compatible with Linked Data principles and leverages some object-oriented concepts to the Web. LDOM makes it possible to define classes together with their associated properties, and to specify additional constraints that valid members of those classes should fulfill. These additional constraints are expressed using SPARQL, yet the structural definitions of associated properties can also be used by tools without a SPARQL processor. In addition to a vocabulary for structural constraints, LDOM includes modularization features that make it possible to define new modeling terms (SPARQL functions and templates) based on executable semantics.

LDOM has a wide range of potential use cases. Its alignment with object-oriented principles means that LDOM can be used to store and share data objects that represent the "model" in applications built with a Model-View-Control architecture. In contrast to most object-oriented systems, RDF adds the value of having a unique identification mechanism for objects (via their URIs), thus also allowing data models to reference each other across the web. Through its foundation on Linked Data principles, LDOM data models are self-describing, which means that applications can dynamically learn about the behavior of objects by resolving URIs. Finally, the structural definitions of classes and properties can be exploited by user interface builders to select suitable display and input widgets.

This document introduces LDOM to people familiar with basic concepts of RDF and SPARQL. A simple model about rectangles and squares is used to introduce all major features of LDOM, including class definitions, constraints, rules, functions and templates. This document can serve as the "Hello, World" example of LDOM. This primer is a possible companion to another document (to be written) that serves as a language reference and full specification.

For the ongoing discussion about the potential name of this technology, see the W3C wiki page.

Introduction

LDOM (Linked Data Object Model) is a modeling language for linked data, based on a minimum sub-set of RDF Schema and object-oriented principles. Features of LDOM include:

LDOM is based on RDF and is compatible with Linked Data principles, making it possible to mix LDOM declarations with models created in other semantic web languages. Other sections elaborate on the relationships of LDOM with RDF Schema and OWL.

This document uses a running example model illustrated in the following UML diagram. In a nut shell, there is a class Rectangle which has a subclass Square, both in the example namespace "ex". All Rectangles can have a width and a height, both integers greater than 0. The area of a Rectangle gets computed by multiplying width and height. Squares must have equal width and height. Rectangles can have one creator, which must be an instance of the class schema:Person.

LDOM definitions are represented in RDF and can be serialized in multiple RDF formats. The example snippets in this document use Turtle [[turtle]] notation. TODO: Future versions should have this switchable between Turtle and JDON-LD [[json-ld]]. You should be familiar with basic RDF concepts [[rdf11-concepts]] such as triples and (for the advanced concepts of LDOM) with SPARQL [[sparql11-overview]].

The Turtle source code of the complete LDOM file can be found at ldomsquare.ldom.ttl.

The LDOM system vocabulary is defined in itself, using its own LDOM File. This file also includes in-line comments for open issues as well as many technical details that are omitted in this primer for space considerations.

Within this document, the following namespace prefix bindings are used:

Prefix Namespace
ldom: http://www.w3.org/ns/ldom/core#
rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
rdfs: http://www.w3.org/2000/01/rdf-schema#
xsd: http://www.w3.org/2001/XMLSchema#
ex: http://example.com/ns#

Class Declarations

Basic class definitions are covered by a subset of RDF Schema (see relationship with RDF Schema), as illustrated in the following example source code:

ex:Rectangle
	a rdfs:Class ;
	rdfs:subClassOf rdfs:Resource ;
	rdfs:label "Rectangle" .

ex:Square
	a rdfs:Class ;
	rdfs:subClassOf ex:Rectangle ;
	rdfs:label "Square" .

The type rdfs:Class (or its subclasses such as owl:Class) are used to declare a class. rdfs:subClassOf is used to indicate that all instances of a subclass are also instances of its superclass(es). The commonly used properties rdfs:label and rdfs:comment are recommended to declare human-readable labels and documentation.

The reuse of the standard RDF Schema terms means that LDOM models can be readily mixed with existing Linked Data models.

LDOM introduces a property ldom:abstract that can be set to true for classes that should not be directly instantiated. Furthermore, classes may be marked ldom:private to indicate that they are only meant to be used inside of the graph that they have been defined in. This can be used to discourage instantiation outside of controlled scenarios.

Note that in contrast to many object-oriented languages, RDF Schema classes may have multiple superclasses. The root class in RDF Schema is rdfs:Resource, and top-level classes in an LDOM model must state explicitly that they are rdfs:subClassOf rdfs:Resource. In other words, each valid LDOM class needs to have at least one named superclass.

Property Declarations

Object-oriented systems have a concept of properties (or fields) that hold attributes and relationships of a given class. The following sections explain how such property attachments can be represented in LDOM.

Basic Property Characteristics

It is common (in UML etc) to specify the name of a property and its cardinality (min/max value count) as well as the value type. In LDOM, these declarations can be attached to a class as follows:

ex:Rectangle
	a rdfs:Class ;
	rdfs:subClassOf rdfs:Resource ;
	rdfs:label "Rectangle" ;
	ldom:property [
		a ldom:PropertyConstraint ;     # This type declaration is optional
		ldom:predicate ex:height ;
		ldom:minCount 1 ;
		ldom:maxCount 1 ;
		ldom:valueType xsd:integer ;
		rdfs:label "height" ;
		rdfs:comment "The height of the Rectangle." ;
	] ;
	ldom:property [
		ldom:predicate ex:width ;
		ldom:minCount 1 ;
		ldom:maxCount 1 ;
		ldom:valueType xsd:integer ;
		rdfs:label "width" ;
		rdfs:comment "The width of the Rectangle." ;
	] ;
	ldom:property [
		ldom:predicate ex:creator ;
		ldom:maxCount 1 ;
		ldom:valueType schema:Person ;
		rdfs:label "creator" ;
		rdfs:comment "The creator of the Rectangle." ;
	] ;

The examples in this document are (currently) all written in Turtle, but here is a snippet previewing how the JSON-LD could look like:

{
	"@context" : [
	    "http://www.w3.org/ns/ldom/context.jsonld",
	    {
	    	"ex" : "http://example.com/ns#"
	    }
	],
	
	"@graph" : [
	    {
	    	"@id" : "http://example.com/ns",
	    	"@type" : "Graph",
	    	"library" : "http://www.w3.org/ns/ldom/core",
	    	"label" : "Test Graph",
	    	"comment" : "This is a comment."
	    },
	    {
	    	"@id" : "ex:Rectangle",
	    	"@type" : "Class",
	    	"subClassOf" : "rdfs:Resource",
	    	"label" : "Rectangle",
	    	"property" : [
	    	    {
	    	    	"predicate" : "ex:width",
	    	    	"minCount" : 1,
	    	    	"maxCount" : 1,
	    	    	"valueType" : "xsd:integer",
	    	    	"label" : "width",
	    	    	"comment" : "The width of the Rectangle."
	    	    },
	    	    ...
	    	]
	    }
	]
}

Tools that understand LDOM can use the information above for many purposes. For example, they can figure out which fields should appear for an input form, and what values those fields can have, as well as labels and comments. Furthermore, they can verify that a given instance of Rectangle has the expected value types and cardinalities for its properties.

The system property ldom:property is used to link a class with its property declarations. Properties get inherited by subclasses. The values of this property are nodes with the following properties:

Property Description
ldom:predicate Required. Must point to the URI of an RDF property used to store the values of the property.
ldom:minCount Type: integer >= 0, the minimum number of values required. Defaults to 0.
ldom:maxCount Type: integer >= 0, the maximum number of values required. Defaults to unlimited.
ldom:valueType an instance of rdfs:Class, the type or datatype that all values of the property must have.
ldom:allowedValues Type: ldom:Set (with property ldom:member), points to a set enumerating the allowed values.
ldom:hasValue points to a specific value that the property must have.
rdfs:label A human-readable label of the property in the context of the associated class.
rdfs:comment A description of the property's role in the context of the associated class.

Datatype Property Characteristics

In addition to those basic property characteristics, it is possible to use others such as min/max value ranges for properties that have datatype literals as values:

ex:Rectangle
	a rdfs:Class ;
	rdfs:subClassOf rdfs:Resource ;
	rdfs:label "Rectangle" ;
	ldom:property [
		ldom:predicate ex:height ;
		ldom:maxCount 1 ;
		ldom:valueType xsd:integer ;
		ldom:minExclusive 0 ;
		...
	] ;

The following built-in constraints are available for datatype values. (XML schema has additional facets: whiteSpace, fractionDigits, totalDigits. Schema.org also suggests: stepValue).

Property Description
ldom:length Type: xsd:integer, number of characters of valid values.
ldom:maxLength Type: xsd:integer, maximum number of characters of valid values.
ldom:minLength Type: xsd:integer, minimum number of characters of valid values.
ldom:maxExclusive Type: the same as the ldom:valueType of the surrounding property.
ldom:maxInclusive Type: the same as the ldom:valueType of the surrounding property.
ldom:minExclusive Type: the same as the ldom:valueType of the surrounding property.
ldom:minInclusive Type: the same as the ldom:valueType of the surrounding property.
ldom:pattern Type: xsd:string, a regular expression to match.

The following example illustrates how a valid instance of the rectangle class can look like. By virtue of the rdf:type triple (abbreviated as a in Turtle), a user interface tool could select appropriate input widgets or validate the instance.

ex:TestRectangle
	a ex:Rectangle ;
	ex:creator ex:PersonWithEmail ;
	ex:height 6 ;
	ex:width 7 ;
	rdfs:label "Test rectangle" .

Inverse Property Declarations

Due to the triple-based data model of RDF, it is possible to "walk" a relationship in both directions - from subject to object and from object to subject. LDOM can be used to declare that a property is associated with a class, even if the predicate is actually used in the inverse direction. As shown below, the system property ldom:inverseProperty is used in such cases, and very similar characteristics as previously mentioned can be applied in these inverse property declarations.

schema:Person
	ldom:inverseProperty [
		ldom:predicate ex:creator ;
		ldom:valueType ex:Rectangle ;
		rdfs:label "created rectangle" ;
		rdfs:comment "Links a Person with all rectangles that he or she created." ;
	] ...

The above instructs a user interface builder that persons can have a property labeled "created rectangle" and defines a suitable value type. Not shown in the example are ldom:minCount and ldom:maxCount, because there may be 0 to infinitely many values in this direction.

Declaring an inverse property is semantically equivalent to having a normal property starting in the related class. From the perspective of the full data model, declaring an inverse property is therefore redundant. However, having an inverse property is often useful to provide a more complete picture in the context of a single resource or class. Furthermore it becomes possible to define more suitable human-readable labels and comments for the inverse direction.

Constraints

The property declarations shown in the previous chapter define conditions that all valid instances of a class need to fulfill. They do this in a declarative language with a limited number of properties such as ldom:maxCount. However, in many cases it is necessary to define additional conditions that are used to verify valid data, or to simply communicate the desired semantics of a model's elements.

SPARQL-based Constraints

For example, the width and height of a Square must be equal. These constraints can be attached to class definitions using ldom:constraint as shown in the next example:

ex:Square
	a rdfs:Class ;
	rdfs:label "Square" ;
	rdfs:subClassOf ex:Rectangle ;
	ldom:constraint [
		ldom:message "Width and height of a Square must be equal" ;
		ldom:path ex:width ;
		ldom:path ex:height ;
		ldom:sparql """
			ASK {
				?this ex:width ?width .
				?this ex:height ?height .
				FILTER (?width != ?height) .
			}
			""" ;
	] ;
.

Open issue: Many people find it confusing that the expression seems to work "backwards" and only find the counter-examples. So the term "constraint" might be misleading. An alternative name "exception" has been proposed (although this term has a different meaning in programming languages). Furthermore, many values of ldom:constraint are in fact template calls, and the user doesn't even see the SPARQL query (e.g. ldon:minCount uses a positive direction even if its internal SPARQL query checks for counter-examples).

The example above uses SPARQL to implement an executable test. The SPARQL query must return true if the condition is violated, using the variable ?this to refer to the currently tested instance. The property ldom:constraint is linking a class with the additional constraints that it needs to fulfill. Each of the values of ldom:constraint can have a ldom:sparql query (ASK, SELECT or CONSTRUCT), or they can be instances of Templates as shown later. In SPARQL-based constraints, the properties ldom:message, ldom:path and ldom:level (with values ldom:Error, ldom:Warning and ldom:FatalError) can be used to provide additional information on the constraint violation.

As alternatives to ASK, you can use SPARQL SELECT or CONSTRUCT queries to take more control over which constraint violations to create. While a little bit more verbose, one advantage of those syntaxes is greater flexibility in how to build error messages etc. The following example implements the same error condition as shown above, but using a CONSTRUCT query. An example of SELECT-based constraints can be found below.

ex:Square
	a rdfs:Class ;
	rdfs:label "Square" ;
	rdfs:subClassOf ex:Rectangle ;
	ldom:constraint [
		ldom:sparql """
			CONSTRUCT {
				_:cv a ldom:Error ;
					ldom:root ?this ;
					ldom:message "Width and height of a Square must be equal" ;
					ldom:path ex:width ;
					ldom:path ex:height 
			}
			WHERE {
				?this ex:width ?width .
				?this ex:height ?height .
				FILTER (?width != ?height) .
			}
			""" ;
	] ;
.

Template-based Constraints

TODO: This section needs work - templates are used but not introduced yet at this stage. The problem is that we want non-SPARQL experts to still be able to use those templates even if they don't understand how they work internally.

In addition to constraints defined in SPARQL, LDOM makes it possible to define constraints using higher-level elements called Templates. (How to define your own Templates is introduced later.) The following example demonstrates the use of the Template ldom:ShapeConstraint which links a property with a "shape" that it needs to fulfill:

ex:Rectangle
	ldom:constraint [
		a ldom:ShapeConstraint ;
		ldom:predicate ex:creator ;
		ldom:some [
			ldom:property [
				ldom:predicate schema:email ;
				ldom:minCount 1 ;
			] ;
		] ;
	] ;

The above means that at least one of the values of the property ex:creator must be an object that has at least one schema:email value. This constraint gets evaluated together with the constraints defined by the property declarations, which means that the ex:creator must also be an instance of schema:Person. The property ldom:some means "at least one" - use ldom:all to specify that all values of the property must match the given shape. Note that the matching values do not have to be instances of the given shape, i.e. no rdf:type triple is required. Shapes can be nested, e.g. using additional ldom:constraint values.

Templates can also be used as values of ldom:property, as long as the template is a subclass of the system template ldom:PropertyConstraint. The LDOM core includes two such templates: ldom:DerivedPropertyConstraint and ldom:PrimaryKeyProperty. Here is an example of the latter, declaring that the values of the property ex:isoCode must be unique for each instance of ex:Country.

ex:Country
	a rdfs:Class ;
	rdfs:subClassOf rdfs:Resource ;
	rdfs:label "Country" ;
  	ldom:property [
  		a ldom:PrimaryKeyPropertyConstraint ;
		ldom:predicate ex:isoCode ;
		ldom:valueType xsd:string ;
		ldom:uriStart "http://example.org/country-" ;
		rdfs:label "ISO code" ;
    ] ...

This type of constraint also specifies how the URIs of instances need to be constructed, by concatenating the provided ldom:uriStart with the value of the primary key. Tools can use this information to automatically create URIs for newly created instances, and for data imported from external non-RDF sources such as relational databases.

Another built-in template is ldom:OrConstraint which can be used to combine multiple other constraint templates to express that at least one of two conditions need to be satisfied. The following example expresses that a ex:RectangleWithArea must either have ex:width and ex:height, or a value for ex:area:

ex:RectangleWithArea
	a rdfs:Class ;
	rdfs:subClassOf ex:Rectangle ;
	ldom:constraint [
		a ldom:OrConstraint ;
		ldom:shape1 [
			ldom:property [
				ldom:predicate ex:width ;
				ldom:minCount 1 ;
			] ;
			ldom:property [
				ldom:predicate ex:height ;
				ldom:minCount 1 ;
			]
		] ;
		ldom:shape2 [
			ldom:property [
				ldom:predicate ex:area ;
				ldom:minCount 1 ;
			]
		]
	] ;
.

The SPARQL query behind the ldom:OrConstraint uses a built-in helper function ldom:hasShape to recursively evaluate the nested shapes. Based on this function, similar templates (such as exclusive-or) could be defined.

Many other kinds of templates can be used from third-party template libraries that provide high-level vocabularies for common design patterns.

Global Constraints

So far all constraint examples had been attached to classes, in an object-oriented style. This has the benefit of a natural way of organizing constraints, and makes it easier for an engine to determine which constraints are relevant for a given resource only. The variable ?this is used in those to refer to the currently evaluated instance.

In some cases, it is necessary to define constraints that do not have a local object scope, but rather apply globally. These can be expressed by instantiating ldom:GlobalConstraint, as shown in the following example.

ex:MyConstraint
	a ldom:GlobalConstraint ;
	ldom:message "Deprecated properties should not be used anywhere." ;
	ldom:level ldom:Warning ;
	ldom:sparql """
			SELECT ?root ?predicate ?value
			WHERE {
				?root ?predicate ?value .
				?predicate owl:deprecated ?any .
			}
		""" ;
.

By default, these constraints are assumed to have a SPARQL query, but it is also possible to instantiate templates. Global constraints should be named with a URI (in this example: ex:MyConstraint) so that they are easier to reference and manage.

Templates

LDOM Templates are "boxed" queries that can be used as values of ldom:constraint and ldom:property (as well as ldom:rule if that gets included into the standard). The role of a template is to encapsulate a reusable piece of SPARQL logic so that users do not need to reinvent the wheel. Templates hide the complexity of the underlying SPARQL query and are therefore suitable for people who are not familiar with SPARQL. The following example declares a LDOM template that can be used for constraints to express that the values of a given property shall be greater than 0.

ex:PositivePropertyValueConstraint
	a ldom:ConstraintTemplate ;
	rdfs:subClassOf ldom:TemplateConstraint ;
	rdfs:label "Positive property value constraint" ;
	ldom:labelTemplate "Values of property {?property} must be > 0" ;
	rdfs:comment """
		A template that can be used to define a LDOM constraint on a given property
		(ex:property) to make sure that the values of that property are > 0.
		""" ;
	ldom:argument [
		ldom:predicate ex:property ;
		ldom:valueType rdf:Property ;
		rdfs:comment "The property to constrain (e.g. ex:width or ex:height)." ;
	] ;
	ldom:sparql """
		SELECT (?property AS ?path) ?message
		WHERE {
			?this ?property ?value .
			FILTER (?value <= 0) .
			BIND (CONCAT("Property ", ldom:label(?property), 
				" must only have positive values, but found ",
				xsd:string(?value)) AS ?message) .
		}
		""" ;
.

In the example above, the template takes an argument, as specified by the ldom:argument. This argument is represented by a value of the property ex:property which is mapped to the variable ?property when the query executes. Here is an example that instantiates, or "calls", the template to define constraints on the properties ex:width and ex:height for all instances of the class ex:Rectangle.

ex:Rectangle
	...
	ldom:constraint [
		a ex:PositivePropertyValueConstraint ;
		ex:property ex:height ;
	] ;
	ldom:constraint [
		a ex:PositivePropertyValueConstraint ;
		ex:property ex:width ;
	] .

When a LDOM engine encounters such a constraint definition, it will execute the ldom:sparql body of the template and pre-bind the declared argument variables with the values specified in the template call. In the case of ex:height, the template's body basically becomes the following, where every appearance of the variable ?property has been replaced with the constant ex:height.

SELECT (ex:height AS ?path) ?message
WHERE {
	?this ex:height ?value .
	FILTER (?value <= 0) .
	BIND (CONCAT("Property ", ldom:label(ex:height), 
		" must only have positive values, but found ", xsd:string(?value)) AS ?message) .
}

LDOM templates make it possible to create libraries of reusable constraints and rules (and other use cases), so that users do not need to learn SPARQL. The LDOM standard comes with several of such reusable constraints including ldom:PropertyConstraint and ldom:Argument which is used by LDOM itself to declare the arguments of templates.

The example above highlights that LDOM templates can be used to create higher-level modeling languages that introduce constructs such as the ex:PositivePropertyValueConstraint above together with semantics that are executable by any LDOM-compliant engine. At the same time, high-level elements such as the property declarations can also be used by other engines that do not necessarily rely on SPARQL.

Profiles

Some applications may only support certain templates as a controlled vocabulary. For example, a JavaScript client form engine may only support property definitions with value type and min/max cardinality. The class ldom:Profile can represent such sets of templates, as illustrated in the following example. Here, an application could use the profile ex:SimpleFormProfile to display warnings if an incoming LDOM model uses features outside of its profile.

ex:SimpleFormProfile
	a ldom:Profile ;
	ldom:member ldom:AbstractCountPropertyConstraint ; # defines ldom:min/maxCount
	ldom:member ldom:AbstractValueTypePropertyConstraint . # defines ldom:valueType

Functions

LDOM Functions are similar to Templates in their syntax, but they are used to declare new SPARQL functions based on an encapsulated, reusable query. The following snippet defines a function ex:computeArea that takes a Rectangle as its argument and returns an integer that is the result of multiplying the Rectangle's width with its height.

ex:computeArea
	a ldom:Function ;
	rdfs:subClassOf ldom:Functions ;
	rdfs:label "compute area" ;
	rdfs:comment "Computes the area of a given rectangle (?arg1) as the product of its width and height." ;
	ldom:argument [
		ldom:predicate ldom:arg1 ;
		ldom:valueType ex:Rectangle ;
		rdfs:comment "The rectangle whose area to compute." ;
	] ;
	ldom:sparql """
		SELECT ((?width * ?height) AS ?result)
		WHERE {
			?arg1 ex:width ?width .
			?arg1 ex:height ?height .
		}
		""" ;
	ldom:returnType xsd:integer ;
.

In LDOM-compliant SPARQL processors, this new function can be used such as in the following example:

SELECT *
WHERE {
    ?rectangle a ex:Rectangle .
    FILTER (ex:computeArea(?rectangle) >= 100) .
}

LDOM functions have a SELECT query as their body, and this query needs to have one result variable (here: ?result). The first binding of this variable will be used as result of the function execution. The execution mechanism is illustrated in the following diagram.

Derived Properties

LDOM includes a special kind of property constraints for properties that are computed (or derived or inferred) from other values. A good example of this is the ex:area property for rectangles:

ex:Rectangle
	...
	ldom:property [
		a ldom:DerivedPropertyConstraint ;
		ldom:predicate ex:area ;
		ldom:maxCount 1 ;
		ldom:sparql "ex:computeArea(?this)" ;
		ldom:valueType xsd:integer ;
		rdfs:label "area" ;
		rdfs:comment "The area of the Rectangle, defined as the product of width x height." ;
	] ;

The ldom:DerivedPropertyConstraint above will flag a constraint violation if the value of ex:area is not equal to the result of the provided SPARQL expression.

Some LDOM implementations may also chose to use constraints of this type in a constructive way, to automatically compute missing values (but this is not covered by the standard).

Rules

(Unclear whether the WG will include inferencing, so this feature is at risk)

LDOM makes it possible to attach executable rules to classes. Rules are represented as SPARQL CONSTRUCT queries that apply to all instances of the associated class and its subclasses. In those rules, the variable ?this refers to each instance of those classes. A LDOM execution engine will make sure that ?this has the correct values. The triples that are constructed by such a rule become "inferred" and are added to the RDF graph, so that other rules can "see" the new triples. In the following example, the value of ex:area gets computed by multiplying the values of ex:width and ex:height.

ex:Rectangle
	ldom:rule [
		ldom:sparql """
			CONSTRUCT {
				?this ex:area ?area .                 # Infer ?area as a value of ex:area
			}
			WHERE {
				?this ex:width ?width .               # Get the width of ?this Rectangle
				?this ex:height ?height .             # Get the height of ?this Rectangle
				BIND ((?width * ?height) AS ?area) .  # Compute area := width * height
			}
		""" ;
	] .

The property ldom:rule is used to link a class with a rule. The values of this property must be either CONSTRUCT queries or template calls that wrap a CONSTRUCT query.

Contexts

LDOM constraints can be grouped into contexts - URIs that have the type ldom:Context. This makes it possible to indicate that certain constraints shall not apply by default, but only for certain applications or user communities. The property ldom:context links an ldom:Constraint with a context:

ex:Rectangle
	ldom:property [
		ldom:predicate dct:publisher ;
		ldom:minCount 1 ;
		ldom:context <http://example.org/trackable>
	] .

In the example above, the class ex:Rectangle has been extended with a minimum cardinality constraint on the property dct:publisher. This constraint is applicable in the provided ldom:context only, which means that it does not apply by default. However, certain applications that process ex:Rectangle instances can trigger the constraint checking in a context that includes all default constraints plus the extra constraints from the http://example.org/trackable context.

The operation that triggers the constraint checking can take included and excluded contexts as argument. Contexts can be organized into hierarchies using ldom:subContextOf, which means that whenever a super-context is requested then all constraints from its sub-contexts also apply. The built-in URI ldom:DefaultContext can be used to specify the default context, and that is also the default value if ldom:context is unspecified.

Graph Management

LDOM models are typically organized in RDF graphs (e.g. stored as files or named graphs on a database). These graphs usually have a URI that helps a system resolve the graph when it is requested. Each LDOM graph may declare an instance of ldom:Graph that has the graph URI as its URI and contains information about the graph itself, including a human-readable label and comments.

For constraint checking and rule execution, LDOM definitions often need to reference other graphs that either contain additional classes, properties and instances, or that may declare templates, rules and constraints that are needed at run-time. LDOM graphs may reference each other via two dedicated properties:

The separation between the graph closures via ldom:include and ldom:library allows LDOM users and implementations to optimize performance because they can exclude certain (library) graphs from the union graph that is used by the SPARQL engine. Furthermore, editing and display tools may chose to hide library graphs as they often contain rather low-level information that is not of interest to average users.

Test Case Vocabulary

It is a well-established practice in software development to define test cases that formalize the expected behavior of a piece of code. In the same spirit, LDOM includes a simple vocabulary to represent constraint checking scenarios together with expected constraint violations. These can be used by modelers to ensure that the constraint definitions are correct, and remain correct as the model evolves.

Due to space considerations, this Primer only covers a small example test case to illustrate the syntax. For details, see the yet-to-be-written formal specification. The example below instructs the LDOM engine to verify that the given resource ex:Father from the given ldom:graph shall be checked for constraints. The test passes "green" if the outcome is exactly one constraint violation that is structurally equivalent to the provided ldom:violation.

ex:TestCase
	a ldom:ResourceConstraintCheckingTestCase ;
	ldom:check ex:Father ;
	ldom:graph <http://www.w3.org/ns/ldom/test/constraint-inverse-001> ;
	ldom:ignore ldom:message ;
	ldom:violation [
		a ldom:Error ;
		ldom:root ex:Father ;
		ldom:path [ ldom:inverse ex:child ] ;
	] .

Relationships with other Languages

The design of LDOM was influenced by a number of other languages.

SPIN

LDOM can be regarded as the next generation of the SPARQL Inferencing Notation (SPIN). SPIN had introduced the concept of attaching SPARQL-based constraints and rules to classes, of Templates, user-defined Functions and template libraries. Notable differences from SPIN include:

Resource Shapes

Resource Shapes 2.0 looks very similar to the structural constraints defined using ldom:property. Here is a rough mapping between the vocabularies:

Resource Shapes LDOM
oslc:property ldom:property
oslc:Property ldom:PropertyConstraint (implicit)
oslc:propertyDefinition ldom:predicate
oslc:defaultValue ldom:defaultValue
oslc:occurs ldom:minCount, ldom:maxCount
oslc:range, oslc:valueType ldom:valueType
oslc:valueShape ldom:all, ldom:some
oslc:allowedValues ldom:allowedValues
dcterms:title rdfs:label
dcterms:description rdfs:comment

ShEx

ShEx borrows and expands on many ideas of Resource Shapes, focusing on nested shape declarations. A unique feature of ShEx is the ShExC compact syntax. A large subset of this syntax could be mapped onto LDOM templates such as ldom:ShapeConstraint.

RDF Schema

LDOM directly reuses some of the main concepts of RDF Schema [[rdf-schema]] models: rdfs:Resource, rdfs:Class, rdfs:subClassOf, rdf:type, rdf:Property and rdfs:Literal (and the built-in datatypes). LDOM relies on class inheritance via rdfs:subClassOf to figure out which constraints to fire, and which properties to inherit, and on rdf:type to link instances with their class definitions. RDF's concept of Linked Data applies to LDOM too, e.g. LDOM engines could look up the definitions of templates and functions by resolving their URIs.

LDOM does not give any special meaning to all other RDF Schema terms including rdfs:subPropertyOf, rdfs:range and rdfs:domain, which means that these are ignored by the standard LDOM semantics. However, it would be possible to define LDOM constraints that interpret selected RDFS vocabulary with closed-world semantics, if that is desirable within certain contexts.

In LDOM it is theoretically not necessary to define rdf:Properties as stand-alone entities - their declaration is optional because all relevant information about the property can be regarded as local to the associated classes only.

Overall, it is perfectly fine to mix existing RDF Schemas with LDOM declarations, either in the same graph or in multiple graphs that reference each other. This way, hybrid models can be created that are interpreted with the traditional open-world semantics of RDF Schema in some scenarios, or the closed-world semantics of LDOM in other use cases. The bulk of instance data can be reused between both worlds.

OWL

The Web Ontology Language (OWL) extends RDF Schema and its original open-world design with a focus on classification problems. The attachment of restrictions to classes is very similar to LDOM. Designing complex class definitions by combining restrictions and other class constructors resembles the concept of nested shapes in ShEx (and ldom:all and ldom:some).

Like with RDF Schema, it is possible to build OWL ontologies that also include LDOM constructs as an additional feature. This also means that the basic structure of most OWL ontologies and their instances can be reused from a LDOM perspective. There are also several implementations of a subset of OWL with closed-world semantics in SPIN, which can be converted to LDOM. LDOM's foundation on SPARQL means that OWL models can be enriched with frequently needed features such as string and mathematical operations, and complex conditions that require variables.

Here is a rough comparison between LDOM elements and their OWL equivalents, assuming a closed-world interpretation of OWL.

OWL LDOM
rdfs:subClassOf an owl:Restriction ldom:property
owl:onProperty ldom:predicate
owl:minCardinality ldom:minCount
owl:maxCardinality ldom:maxCount
owl:allValuesFrom ldom:all or ldom:valueType
owl:someValuesFrom ldom:some
owl:oneOf ldom:allowedValues
owl:hasKey (without URI rule) ldom:PrimaryKeyPropertyConstraint

RDFUnit

The discussions in the Shapes WG led to refinements of the constraint violation syntax that also exist in RDFUnit. Also, RDFUnit has a notion of TestCases which inspired the design of the ldom:TestCase class. Furthermore, the concept of ldom:Context borrows ideas from the RDFUnit properties appliesTo and source.