+LinkML Instances
+Functional Instance Syntax and Structure
+This specification provides a grammar for a functional syntax for
+expressing LinkML instances. This syntax is not intended for data
+exchange, but instead for unambiguous describing data in LinkML.
+Section 6 specifies how the instance model is converted to JSON, YAML, and RDF.
+Instances
+An instance is either one of four definition types, or a collection, or the special token None
:
+
+Instance := None | InstanceOfClass | InstanceOfType | InstanceOfEnum | InstanceOfReference | CollectionInstance
+AtomicInstance :=
+
+classDiagram
+ Instance <|-- InstanceOfClass
+ Instance <|-- AtomicInstance
+ AtomicInstance <|-- InstanceOfReference
+ AtomicInstance <|-- InstanceOfType
+ AtomicInstance <|-- InstanceOfEnum
+ Instance <|-- CollectionInstance
+ Instance <-- None
+
+
+Definition Types and Names
+Definition names are used to unambiguously indicate definitions specified in a schema
+ClassDefinitionName := ElementName
+ClassDefinitionReferenceName := ElementName
+TypeDefinitionName := ElementName
+EnumDefinitionName := ElementName
+SlotDefinitionName := ElementName
+ElementName := a finite sequence of characters matching the PN_LOCAL production of SPARQL and not matching any of the keyword terminals of the syntax
+Note that the grammar needs a table mapping names to types in order to
+unambiguously parse a serialization in functional syntax
+names must not be shared across definition types
+Instances of Classes
+An InstanceOfClass is a pair consisting of (1) a ClassDefinition Name that indicates the instantiation type of the instance, and (2) zero to many Assignments, where each
+assignment is a key-value pair of a SlotName and an Instance* value.
+InstanceOfClass := ClassDefinitionName '(' <Assignment>List ')'
+Assignment := SlotName '=' Instance
+classDiagram
+ Instance <|-- InstanceOfClass
+ InstanceOfClass "0..*" *--> Assignment
+ Assignment "1" --> Instance
+
+ class InstanceOfClass {
+ +ClassDefinitionName type
+ +Assignment assignments
+ }
+ class Assignment {
+ +SlotDefinitionName slot
+ +Instance value
+ }
+
+No SlotName can appear twice in any set of Assignments (i.e. SlotName is a key)
+An example instance might be written in functional syntax as:
+Person(id=...,
+ name=...,
+ age=...,
+ <other Assignments>)
+
+Where this instantiates the class Person.
+Schemas
+The set of permitted slots for a class is defined by LinkML
+schema. Schemas are covered in the next section.
+An instance can be syntactically valid (i.e conforming to the
+grammar defined in this section) while structurally invalid (i.e not
+conforming to a schema). Section 5 covers validation.
+Primitive (Atomic) Instances
+There are 3 types of primitive instances, each is a pair consisting of (1) a Name of the element instantiated (2) an atomic value
+InstanceOfType := TypeDefinitionName '(' AtomicValue ')'
+InstanceOfEnum := EnumDefinitionName '(' AtomicValue ')'
+InstanceOfReference := ClassDefinitionReferenceName '(' AtomicValue ')'
+classDiagram
+ Instance <|-- AtomicInstance
+ AtomicInstance <|-- InstanceOfReference
+ AtomicInstance <|-- InstanceOfType
+ AtomicInstance <|-- InstanceOfEnum
+ class Instance {
+
+ }
+ class AtomicInstance {
+ +AtomicValue value
+ }
+ class InstanceOfReference {
+ +ClassDefinitionName type
+ }
+ class InstanceOfType {
+ +TypeDefinitionName type
+ }
+ class InstanceOfEnum {
+ +EnumDefinitionName type
+ }
+
+Atomic Values
+An atomic value is either a string or number or boolean, where numbers can be floating points, decimals, or integers.
+AtomicValue := StringValue | NumberValue | BooleanValue
+StringValue := a finite sequence of characters in which " (U+22) and \ (U+5C) occur only in pairs of the form \" (U+5C, U+22) and \ (U+5C, U+5C), enclosed in a pair of " (U+22) characters
+NumberValue := FloatingPointValue | DecimalValue | IntegerValue
+FloatingPointValue ::= [ '+' | '-'] ( Digits ['.'Digits] [ Exponent ] | '.' Digits [ Exponent ]) ( 'f' | 'F' )
+Exponent ::= ('e' | 'E') ['+' | '-'] Digits
+DecimalValue ::= ['+' | '-'] Digits '.' Digits
+IntegerValue ::= ['+' | '-'] Digits
+NonNegativeInteger ::= Zero | PositiveInteger
+PositiveInteger ::= NonZero { Digit }
+Digits ::= Digit { Digit }
+Digit ::= Zero | NonZero
+NonZero := '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
+Zero ::= '0'
+BooleanValue ::= 'True' | 'False'
+Examples of atomic values are:
+
+180.2
-- a DecimalValue
+5
-- an IntegerValue
+"Alex"
-- a StringValue
+
+Atomic Instance Examples
+An InstanceOfType instance might look like:
+Integer(23)
+
+For this to be a valid InstanceOfType, "Integer" must be the name of a TypeDefinition in the schema
+Another exampleL
+PhoneNumber("+1 800 555 0100")
+
+For this to be a valid InstanceOfType, "PhoneNumber" must be the name of a TypeDefinition in the schema
+If the schema includes a ClassReference "PersonId" then the following is a valid InstanceOfReference
+PersonId("SSN:456")
+
+This MAY be the same string used to identify an instance of a ClassDefinition Person(id="SSN:456")
, but this is not required.
+Collections
+A collection is zero or more instances, serialized as a comma-delimited list:
+CollectionInstance := '[' <Instance>List ']'
+
+classDiagram
+Instance <|-- CollectionInstance
+CollectionInstance "0..*" --> Instance
+
+Examples of collections:
+
+[String("A"), String("B"), Integer(5)]
-- a list of primitive instances
+[Person(name=..., ...), Person(name=..., ...)]
-- a list of class instances
+[Person(name=..., ...), Integer(5), None]
-- a heterogeneous collection
+[]
-- an empty collection
+
+None (Null) instances
+A special symbol is included to indicate null or missing values
+None := 'None'
+An assignment of a slot to None is equivalent to omitting that assignment. I.e. the following two instance serializations are equivalent:
+Person(address=None)
+
+Person()
+
+Combined Example
+The following is an example of an instance of a ClassDefinition called Person:
+Person(
+ id=String("SSN:123"),
+ name=String("Alex"),
+ aliases=[String("Alexandra")],
+ address=None,
+ phone=PhoneNumber("+1 800 555 0100"),
+ height=
+ Measurement(value=Decimal(170.2)
+ unit=UnitCode("cm")),
+ relationships=[
+ FamilialRelationship(
+ type=RelationshipType("SIBLING_OF"),
+ related_to=PersonId("SSN:456")
+ )
+ ]
+)
+
+See (YAML-Mapping)[#YAML-Mapping] for an example of the equivalent structure expressed in YAML.
+Parsing this requires a table that maps definition names to schema element types:
+
+
+
+Definition Name |
+Type |
+
+
+
+
+Person |
+ClassDefinition |
+
+
+Measurement |
+ClassDefinition |
+
+
+FamilialRelationship |
+ClassDefinition |
+
+
+UnitCode |
+EnumDefinition |
+
+
+Person |
+ClassDefinition |
+
+
+
+Identity conditions
+For two instances i
and j
to be identical they must be of the same metatype.
+Identity conditions for two primitive instances are satisfied if both DefinitionName and AtomicValue match
+None is identical to itself
+Two collections are identical if they are of the same length and each member of i
is identical to at least one member of j
+Two ClassDefinition instances are identical if the instantiated ClassDefinitionName is identical and each non-None assignment
+in i is identical an assignment in j
and, and each non-None assignment in j
is identical to an assignment in i
+Two assignments are identical if the slot name is the same, and the value is identical
+Instance Serializations
+The abstract syntax provided here is intended as a normative syntax for the purposes
+of specifying the semantics of LinkML.
+See future sections for details on how this functional syntax maps to other serialization
+syntaxes and models such as JSON and RDF.
+Instance Accessor Syntax
+For a given instance i
, accessor syntax can be used to dereference values.
+Path := Source { PathExtension }
+PathExtension := '.' SlotDefinitionName | '[' Identifier ']'
+To interpret an accessor for a given instance i:
+
+- if the path extension is
.<s>
then i must be a ClassDefinition instance, and the value is equal to the value of the slot assignment for slot s
+- if the path extension is
[<id>]
then i must be a Collection instance, and the value is equals to the member of that list that has a slot with the role of identifier whose value is <id>
+
+For example, if i is equal to the Person instance in the example above:
+
+i.id
== String("SSN:123")
+i.height.unit
== String("cm")
+
+