Preamble¶
What’s in this document?
This introductory SOML section provides information about the metadata, configuration, and prefixes of a schema. It also describes some common concepts applicable throughout the schema, such as naming convention, IRI processing, and reserved words.
Schema Metadata¶
You can provide some info (metadata) about the schema.
id: /soml/some-domain
label: Some Domain schema
created: 2019-04-15
updated: 2019-05-10
creator: http://ontotext.com
versionInfo: 1.0
Note
It is highly recommended to provide an id
. If you do not do so, the Semantic Objects will generate a random id
when you post the schema to the Semantic Objects, but you should use this only in testing and never in production.
All other fields are optional and have sensible defaults.
id
: used for SOML operations (create, update, delete) by the Semantic Objects. It should start with/soml/
.versionInfo
: the version of the schema (SOML instance and corresponding ontology), not a version of the SOML language.
The rest of the preamble defines prefixes (namespaces) that are used to map object and prop names to IRIs as used in RDF.
Schema Configuration¶
You can provide configurations that are specific to the current schema.
id: /soml/some-domain
label: Some Domain schema
versionInfo: 1.0
config:
enable_mutations: true
lang: {fetch: "en", validate: "UNIQ", implicit: "en", defaultNameFetch: "ANY", appendDefaultNameFetch: true} # or lang: "en"
queryPfx: ""
mutationPfx: ""
nullJsonArrays: false
All of the supported configurations are optional and have reasonable defaults.
The currently supported keys are:
enable_mutations
: with possible valuestrue
(default) /false
. Controls whether the generated GraphQL schema should include object mutations or not. To learn more about GraphQL mutations, see the GraphQL Mutation Tutorial.Note
This option cannot override the service configuration graphql.mutation.enabled=false to forcefully enable mutations.
lang
: provides a schema level default forlangString
language handling.
defaultNameFetch
: specifies the default fetch spec to use or append to thename
fetch spec. Default value isANY
.appendDefaultNameFetch
: specifies whether the default spec, if any, should be appended or not to any user-defined name fetch spec. Default value istrue
.The configuration values above are for illustration purposes. For more information how to configure the language handling, see the Language Configurations section. For more information about
name
fetching, see the Interface Nameable section.
queryPfx
: allows setting a prefix that will be put in all queries in the GraphQL schema. Does not have a default value.Example:
If not configured, the query for the type
Person
will look like this:type Query { person(orderBy: Person_OrderBy, limit: PositiveInteger, offset: PositiveInteger, ID: [ID!], where: Person_Where_Multi, lang: String): [Person]! }But if changed to
queryPfx: query_
, for example, the query would look like this:type Query { query_person(orderBy: Person_OrderBy, limit: PositiveInteger, offset: PositiveInteger, ID: [ID!], where: Person_Where_Multi, lang: String): [Person]! }
mutationPfx
: allows setting a prefix that will be put in all mutations in the GraphQL schema. Does not have a default value.Example:
If not configured, the mutation queries for the type
Person
will look like this:type Mutation { create_Person(objects: [Person_Create_Input!]): Person_Mutation_Response update_Person(objects: Person_Update_Input!, where: Person_Where_Multi): Person_Mutation_Response delete_Person(where: Person_Delete_Filter!): Person_Mutation_Response }But if changed to
mutationPfx: mutation_
, for example, the mutations would look like this:type Mutation { mutation_create_Person(objects: [Person_Create_Input!]): Person_Mutation_Response mutation_update_Person(objects: Person_Update_Input!, where: Person_Where_Multi): Person_Mutation_Response mutation_delete_Person(where: Person_Delete_Filter!): Person_Mutation_Response }
nullJsonArrays
: changes the default behavior on how to interpret missing data for multi-valued properties. If set totrue
, multi-valued properties will be returned asnull
instead of empty array[]
. The default value isfalse
.Example:
Given a property
friends
of typePerson
that has no values, the following behavior can be observed:
Array definition nullJsonArrays: true nullJsonArrays: false [Person] null [] [Person]! error, destroy parent [] [Person!] null [] [Person!]! error, destroy parent [] For more information, see Property Nullability.
Special Prefixes¶
specialPrefixes:
base_iri: http://example.org/resource/
vocab_iri: http://example.org/vocabulary/
vocab_prefix: voc
ontology_iri: http://example.org/vocabulary
shape_iri: http://example.org/shape/
The special prefixes (namespaces) include:
base_iri
: base IRI for data (resources), used in SOML characteristics such astype
andprefix
. We currently use full IRIs in GraphQL queries and responses, but in the future may shorten them using the base (see Naming Convention and IRI Processing).vocab_iri
: default namespace for vocabulary (ontology) terms, i.e. object and prop names. SOML allows the use of multiple ontologies (see Own Prefixes) through underscore prefixes likepfx_prop
, and one of them is designated as default so it can be used without prefix.vocab_prefix
: prefix corresponding to the vocab IRI. The vocabulary prefix is not materialized in the GraphQL schema for ordinary properties. For example, ifprop
is defined aspfx:prop
, it will be visualized simply asprop
. However,name
(which is a reserved word) has to be defined aspfx:name
to avoid collision with the predefined property, and will be visualized aspfx_name
. The same applies toid
andtype
, which are reserved words as well.- It must be used in SOML for prop names that conflict with a reserved word (see Reserved Words)
- It is also useful in languages that do not have such a concept (e.g., Turtle), as we do not like to use an empty prefix.
The following IRIs may be used in the future:
ontology_iri
: an RDF Ontology IRI used to make statements about the ontology. Typically, it is the same as the vocab IRI but without a trailing slash or hash.shapes_iri
: RDF Shapes IRI: all generated shapes live under this IRI.
Predefined Prefixes¶
SOML predefines a few commonly used prefixes such as dct: gn: owl: rdf: xsd:
, and some more exotic prefixes:
puml:
: used by the rdfpuml diagramming tool.so:
: in the future may transmit in JSON-LD built-in SOML properties likeso:name
andso:type
.res:
: in the future may transmit in JSON-LD dynamic properties calculated in queries.
prefixes:
# common prefixes
so: http://www.ontotext.com/semantic-object/
res: http://www.ontotext.com/semantic-object/result/
dct: http://purl.org/dc/terms/
gn: http://www.geonames.org/ontology#
owl: http://www.w3.org/2002/07/owl#
puml: http://plantuml.com/ontology#
rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns#
rdfs: http://www.w3.org/2000/01/rdf-schema#
skos: http://www.w3.org/2004/02/skos/core#
void: http://rdfs.org/ns/void#
wgs84: http://www.w3.org/2003/01/geo/wgs84_pos#
xsd: http://www.w3.org/2001/XMLSchema#
The Special Prefixes shown in the previous section and those above are predefined and may be used without having to define them (but can be overridden): This means that a valid SOML does not need to define any prefixes.
- A plain name like
Obj
orprop
is mapped usingvocab_iri
, which by using the predefined prefixes maps tovoc:Obj
orvoc:prop
respectively, and thus tohttp://example.org/vocabulary/
IRIs. - Of course, in a real application you would want to define your own special prefixes.
Own Prefixes¶
You can also define your own prefixes for your domain, e.g.,:
prefixes:
# schema-specific prefixes
sw: https://swapi.co/vocabulary/
dbr: http://dbpedia.org/resource/
dbo: http://dbpedia.org/ontology/
Rules:
- Each prefix should conform to the Turtle grammar production PN_PREFIX.
- Prefixes should not mask defined IRI schemes such as
http: https: mailto: ftp: mailto: urn: geo:
. (In some cases, you may want to break this guideline for convenience, e.g., the schema.org JSON-LD context defines a prefixgeo:
that breaks it.)
Naming Convention and IRI Processing¶
Class and property names (the YAML key) play several important roles:
- They are used in SOML to describe objects, properties, and the connection between them.
- They (together with
prefixes
andvocab_iri
) are used to derive RDF IRIs. - They are used in GraphQL as type and field names.
pfx:name
is translated topfx_name
to make it GraphQL and JSON friendly.
If a name includes :
, the part before it must be a defined prefix (see Own Prefixes).
The local parts of property and class names (part after :
if any) must comply with the following naming conventions:
- Prop names must start with a lowercase Unicode letter, and are recommended to follow a
lowerCamelCase
convention. - Class names must start with an uppercase Unicode letter, and are recommended to follow an
UpperCamelCase
(also calledPascalCase
) convention. - Both must conform to the Turtle grammar production PN_PREFIX. Please note that this is stricter than RDF and Turtle local name conventions.
- Cannot start with two underscores
__
, which is reserved for GraphQL introspection. - If they include an underscore, they cannot start with
pfx_
wherepfx:
is a defined prefix. Usepfx:name
if you mean that prefix, orvoc:pfx_name
if you mean the default vocab namespace (see Special Prefixes) - Cannot be a reserved word, see Reserved Words.
Names in SOML are converted to IRIs as follows:
- If the prop has characteristic
rdfProp
, use that instead of the name. - If a name starts with a defined prefix
pfx:
, replace the prefix with the corresponding IRI. - Otherwise, prepend
vocab_iri
.
Strings in the type
and rdfProp
characteristics are converted to IRIs as follows:
- If the string starts with a defined IRI scheme, use it directly (absolute IRI).
- Else if the string starts with a defined prefix
pfx:
, replace the prefix with the corresponding IRI (prefixed IRI). - Else if the string includes only Unicode alphanumerics and
[-._]
, prependvocab_iri
(relative ontology IRI). - Else prepend
base_iri
(relative instance IRI). Typically, such a string will include/
or#
and is used in thetype
characteristic to designate a “business type” not defined in an ontology, e.g., askos:ConceptScheme
IRI.
GraphQL queries and JSON responses use absolute IRIs for iri
fields. This includes:
- the
id
field of every object, which is its IRI. - fields of type
iri
(e.g.,websiteUrl
of a company) that reference external resources. - the
type
field, which is the datatype of Literals orrdf:type
of objects (most of the time you will not need to specify these explicitly).
We are planning to use Compact URIs (CURIEs) in the future to shorten GraphQL queries and JSON responses (see CURIE in Wikipedia and the CURIE W3C TR) but it has not been done yet as it may may cause confusion in some cases. If you would like to use CURIEs, please do send us your feedback about it.
Reserved Words¶
The following reserved words cannot be used as prop names:
id
: the node IRI that is a mandatory field for every object (the GraphQL typeID!
is used)type
: therdf:type
of objects or the datatype of scalarslang
: the language tag of a Literal or langStringvalue
: the value of a Literalname
: a uniform preferred name for an object
The following reserved words cannot be used as object names:
Literal
: together withlang
,type
, andvalue
, it is used to represent an RDF literalObject
: an interface for common functionality: the presence ofid
andtype
Nameable
: an interface used for the presence ofname
To use such prop/object names in the vocab namespace, you need to spell them out in full, e.g., voc:type voc:name voc:Object
.
GraphQL descr Directive¶
Objects and properties have label
and descr
.
These are emitted separately in GraphQL, so they can be used more conveniently in a UI app.
Label
comes before the object/prop as a “string”: this is a standard GraphQL feature.Descr
comes after the object/prop as a@descr
directive.
For example, this SOML property:
prefName: {label: "Preferred name", min: 1, descr: "A single selected name"}
Is emitted in GraphQL as follows:
"Preferred name"
prefName: String @descr(_:"A single selected name") @constraints(minCount : 1, maxCount : 1)
The directive is defined as follows:
directive @descr(_:String!) on FIELD_DEFINITION | OBJECT | INTERFACE
According to the GraphQL specification,
directive values are not returned as part of GraphQL schema introspection.
This problem is discussed in issue graphql-spec#300: we have added @descr
as a use case, and return the directive value anyway.