Creating and extending ontology
Telicent CORE can support any RDF-based ontology. However, there will be times where you need to make extensions to existing ontologies e.g. extending an ontology that has a class called RoadVehicle
to support specific subtypes e.g. Van
, EstateCar
etc. You may also want to utilize other ontologies other than the default ontologies that come out-of-the-box with CORE. In both these cases, the specification of new ontology splits into two concerns:
- The actual RDF specification of classes and properties some of which might be extensions of other ontologies.
- The specification of ontology styles, used to prescribe how data using an ontology appears within the Telicent Apps e.g. icons and colors.
Here we will explain how to do both, and how to get these two types of specification, into CORE.
Specifying Ontology (new classes and properties)
Creating an ontology from scratch is a significant undertaking, so starting with one of the existing ontologies supported by Telicent CORE can be a practical choice. Whether you choose IES4 or another, you might find they do not offer sufficiently specific classes to meet your needs. Most formal ontologies cater for a large number of domains making them wide in scope but not necessarily deep in any one area. For example, IES4 includes a class called Ship
. However if you might need something more specific like PassengerShip
, you need to make an extension of Ship
. This guide will walk you through the practical steps of extending an ontology. We’ll use IES4 as an example, but these steps can be applied to extending any ontology.
If you’re interested in learning more about extending IES4 specifically, including considerations on where to make your extensions in the IES4 hierarchy, you can find additional information here.
Step-by-step guide
First we need to create RDF that defines a new resource; which could be either a class or a property. This RDF will define the name of the new resource and what it is an extension of. When either extending or creating a new ontology, we need to choose a namespace for all of its resources. When choosing a namespace for your ontology, choose a descriptive name and use a domain that you control (or one that is not already in use). See Sir Tim Berners-Lee article on selecting good namespaces and URIs here. Remember, all namespaces end with either /
or #
, after which you can place the name of your new resource.
For each resource we want to add to our ontology, we need to specify in our RDF at least three triples:
- A triple which specifies what kind of resource we are defining by using the predicate
rdf:type
.- For classes this will be either
rdfs:Class
orowl:Class
. - For properties that relate one resource to another i.e. a relationship, this will be either
rdfs:Property
orowl:ObjectProperty
- For properties that add literals to a resource i.e. an attribute, this will be either
rdfs:Literal
orowl:DataProperty
. Note, OWL has many others. You should generally follow what has already been used in any ontology you intend to extend. We generally find using RDFS is a lot more straightforward than using OWL.
- For classes this will be either
- A triple to specify what your extension is from. Note, a resource can extend more than one other resource:
- For classes this is defined using the property
rdfs:subClassOf
- For all types of property, this is defined using the property
rdfs:subPropertyOf
Note, there are no OWL alternatives to these.
- For classes this is defined using the property
- A triple to provide a human-readable key for the resource. For all resources this is using the property
rdfs:label
orskos:prefLabel
.
So to illustrate the above, using a new namespace for our ontology of http://example.com/local-ontology#
, our definition of the new classes of PassengerShip
and CargoShip
as extensions of IES4, would look like this:
# Using Turtle Syntax
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix ies: <http://ies.data.gov.uk/ontology/ies4#> .
@prefix ont: <http://example.com/local-ontology#> .
ont:PassengerShip rdf:type rdfs:Class .
ont:PassengerShip rdfs:subClassOf ies:Ship .
ont:PassengerShip rdfs:label "Passenger Ship" .
ont:CargoShip rdf:type rdfs:Class .
ont:CargoShip rdfs:subClassOf ies:Ship .
ont:CargoShip rdfs:label "Cargo Ship" .
An example of adding a property is provided below:
# Using Turtle Syntax
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix ies: <http://ies.data.gov.uk/ontology/ies4#> .
@prefix ont: <http://example.com/local-ontology#> .
ont:isMotherOf rdf:type owl:ObjectProperty .
ont:isMotherOf rdfs:subPropertyOf ies:isParentOf .
ont:isMotherOf rdfs:label "is mother of" .
Specifying Ontology Styles
Now that we have defined our extension(s) we can think about the appearance of the new classes in CORE. Note, we normally do not style properties. We specify the styles for a given class by added a fourth and final triple to the RDF specification of a class. This triple uses the predicate <http://telicent.io/ontology/style>
and has an object literal which is a stringified JSON of style information. So for our ont:PassengerShip
example, the full definition for the class including style information looks like this:
# Using Turtle Syntax
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix ies: <http://ies.data.gov.uk/ontology/ies4#> .
@prefix ont: <http://example.com/local-ontology#> .
@prefix tont: <http://telicent.io/ontology/> .
ont:PassengerShip rdf:type rdfs:Class .
ont:PassengerShip rdfs:subClassOf ies:Ship .
ont:PassengerShip rdfs:label "Passenger Ship" .
ont:PassengerShip tont:style "{\"defaultStyles\": {\"dark\": {\"backgroundColor\": ... }}" . # etc
The JSON object used as the object of the triple looks like the below:
{
"defaultStyles": {
"dark": {
"backgroundColor": "#242400",
"color": "#FFFD04"
},
"light": {
"backgroundColor": "#242400",
"color": "#FFFD04"
},
"shape": "round-circle",
"borderRadius": "9999px",
"borderWidth": "2px",
"selectedBorderWidth": "3px"
},
"defaultIcons": {
"riIcon": "ri-meteor-line",
"faIcon": "fa-solid fa-ship",
"faUnicode": "\uf21a",
"faClass": "fa-solid"
}
}
Below we provide a description of each of the fields in this JSON object.
Key | Value Example | Description |
---|---|---|
backgroundColor | #242400 | The dark colour for styling a class, the inside of a node |
color | #FFFD04 | The light colour for styling a class, the icon and node outline |
size | M | The size of the node (S, M, L) |
shape | circle | The shape of the node |
faIcon | fa-solid fa-ship | The Font Awesome icon for the node |
faUnicode | \uf21a | The Font Awesome unicode for the icon. This must be from the free set. |
faClass | fa-solid | The Font Awesome icon type. This must be from the free set. |

We also provide the JSON schema for this structure below:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"defaultStyles": {
"type": "object",
"properties": {
"dark": {
"type": "object",
"properties": {
"backgroundColor": { "type": "string" },
"color": { "type": "string" }
},
"required": ["backgroundColor", "color"]
},
"light": {
"type": "object",
"properties": {
"backgroundColor": { "type": "string" },
"color": { "type": "string" }
},
"required": ["backgroundColor", "color"]
},
"shape": { "type": "string" },
"borderRadius": { "type": "string" },
"borderWidth": { "type": "string" },
"selectedBorderWidth": { "type": "string" }
},
"required": ["dark", "light", "shape", "borderRadius", "borderWidth", "selectedBorderWidth"]
},
"defaultIcons": {
"type": "object",
"properties": {
"riIcon": { "type": "string" },
"faIcon": { "type": "string" },
"faUnicode": { "type": "string" },
"faClass": { "type": "string" }
},
"required": ["riIcon", "faIcon", "faUnicode", "faClass"]
}
},
"required": ["defaultStyles", "defaultIcons"]
}
Get your new ontology and styles into CORE
Once you have your ontology and ontology styles serialized as RDF, you can use an adapter to get both into CORE. There is a dedicated ontology
topic for such.