The LinkML model provides a fixed set of metamodel slots which can be applied to any schema element.
Examples of these are:
description - a human readable description of the element
comments - a human readable comment about the element
aliases - a set of alternative names for the element
deprecated - a boolean flag indicating that the element is deprecated
seeAlso - a set of URIs that provide additional information about the element
If you attempt to assign a slot that is not in the metamodel, you will get an error. For example,
if you wanted to add a
review slot to the
Person class like this:
classes: Person: description: A person, living or dead review: A very useful class that is well defined attributes: id: ...
This will result in an error, because
review is not a metamodel slot.
This conformance to a single metamodel can be useful for ensuring consistency and interoperability among LinkML schemas. However, it can be too constraining in some cases. To get around this, the LinkML metamodel has a generic annotations slot that can be used to assign arbitrary tags and values to any schema element.
Adding your own annotations#
In the above case, we can add the
review annotation to the
Person class like this:
classes: Person: annotations: review: A very useful class that is well defined ...
Note also that prior to LinkML 1.6, the range of the annotation value was
string, but in 1.6 and higher,
the range can be any object.
By default, all annotation tags and values are valid. Feel free to add whatever annotations you like to any schema element - classes, enums, permissible values, slots, even schemas themselves.
However, if you want to restrict the set of valid annotations, you can do this starting from LinkMK 1.6, where you can treat annotation tags as if they were slots in your own metamodel extension.
This is done by adding an instantiates slot-value assignment onto any schema element. The range of
instantiates slot is a
uriorcurie that references a class that serves as a metamodel extension class.
For example, given our example schema fragment, we can add an
instantiates slot to the
stating that this class is an instance of the
Reviewable metamodel extension class:
classes: Person: instantiates: - mymetamodel:Reviewable annotations: review: A very useful class that is well defined ...
This metaclass extension can live in the same schema, or in a different schema. This is why they are referenced
uriorcurie rather than a local name.
Reviewable class might be defined as follows:
id: https://example.org/mymetamodel/ name: mymetamodel ... classes: Reviewable: class_uri: mymetamodel:Reviewable attributes: review: description: an expert review of a schema element range: string
This can be thought of as a schema element mixin class - the class defines the extra slots that can be attached to schema elements via annotations.
Other schema elements can also instantiate the
classes: Person: instantiates: - mymetamodel:Reviewable annotations: review: A very useful class that is well defined ... attributes: name: description: the name of a person instantiates: mymetamodel:Reviewable annotations: review: A very useful attribute that is well defined ...
Note that here the
attributes section of the
Person definition is the attributes that an
Person may have. The
annotations section pertains to the class Person, not instances.
Validation of annotations#
If a schema element does not instantiate a metamodel extension class, then any annotation tag is valid.
(this is already the case for all pre 1.6 schemas, since the
instantiates slot is not defined in previous
versions of the metamodel).
If a schema element does instantiate a metamodel extension class, then the set of valid annotation tags should conform to the slots defined in the metamodel extension class, as if the annotation tags were first-class slots, and instantiates value was a mixin.
However, this is not yet supported in the current LinkML validator, so using
instantiates indicates your
intent, but does not yet enforce validation.
Other uses of instantiates#
instantiates slot can also be used constrain rather than extend.
For example, to define a strict metamodel element that must have a description:
id: https://example.org/mymetamodel/ name: mymetamodel ... classes: StrictElement: class_uri: mymetamodel:StrictClassDefinition slot_usage: description: required: true
Any schema element that instantiates
StrictElement must have a description:
classes: Person: instantiates: - mymetamodel:StrictElement description: A person, living or dead ## must be provided