Documentation/Extensions

Developing GoodRelations Extensions for Vertical Industries

See also: List of existing extensions for GoodRelations

Purpose of this document

This document explains how ontologies describing product and services categories plus their attributes must be designed in order to be compatible with the GoodRelations ontology.

Prerequisites

In order to use this document, you should be familiar with ontology engineering in RDF-S and OWL and respective tools (e.g. Protégé).

Overview

The GoodRelations ontology consists of two parts:

a) a set of elements for describing Web offerings. Web offerings are basically statements made via a Web resource that some legal entity is offering to e.g. sell, lease out, or repair a certain good, or to provide a certain service and

b) a small top-level ontology for products and services ontologies. This part defines a few very important abstract elements which are meant to be specialized by a particular products or services ontology.

In this document, we describe the top-level part of GoodRelations only (b), because that must be the basis for every products or services ontology. While it may also make sense to import and refine part a) of GoodRelations in some scenarios, this is outside the scope of this document.

Key Elements of Products and Services Ontologies

Each product or services ontology typically defines elements of the following fundamental types:

Product or Services Classes:Categories of products or services that provide the same functionality or benefit, or that are of the same nature. Examples are "TV set", "digital Camera", "laptop computer", etc. Services classes summarize activities, e.g. "hairdressing" or "dry cleaning". Note that such classes are vendor-neutral and not to be mixed up with product models (like a particular car make and model - "Ford T" or "VW Golf").

Properties: An instance of a products or services class can be described in more detail using properties. For example, a TV set can be described by its screen size, a laptop computer by its weight, etc.

Properties can be either qualitative or quantitative: Qualitative properties are such that refer to a single value from a given set of possible values, or such that refer to text data or simple yes/no decision s (e.g., that are of type boolean).

Quantitative propertiesare such that refer to a quantitative measurement, which can at least theoretically be specified as a range. Examples are screen size, weight, seating capacity, operating voltage, etc.

Value sets and Values:For qualitative values, it is often helpful to define the allowed values as a fine set of individuals. For example, if cellphones have the qualitative property "hasBatteryType", it may make sense to define a class for all battery types named "BatteryType" and two allowed value instances "Lithium-ion" and "Nickel metal hydride" .

In GoodRelations, we know the following three fundamental types of properties for product features:

  • datatypeProductOrServiceProperty: This property is the super property for all pure datatype properties that can be used to describe a product and services instance. Only such properties that are no quantitative properties and that have no predefined value instances are subproperties of this property. In practice, this refers to a few integer properties for which the integer value represents qualitative aspects, for string datatypes (as long as no predefined values exist), and for boolean datatype properties.
  • qualitativeProductOrServiceProperty: This is the super property of all qualitative properties for products and services. All properties for which value instances are specified are subproperties of this property.
  • quantitativeProductOrServiceProperty:This is the super property of all quantitative properties for products and services. All properties that specify quantitative characteristics, for which an interval is at least theoretically an appropriate value, are specified are subproperties of this property. The actual range for such values can be either an integer interval or a float interval.

For reasons explained in more detail in the GoodRelations technical report, datatypeProductOrServicePropertyis an owl:DatatypeProperty, and both qualitativeProductOrServiceProperty and quantitativeProductOrServicePropertyare owl:ObjectProperties. In short this is because ranges are represented in GoodRelations as instances of a QuantitativeValue class, for they can otherwise hardly be represented in OWL.

Building your OWL Products and Services Ontology: Domain Capture

The basic approach for building a domain-specific products and services ontology is pretty straightforward:

Hint on Naming: We suggest that you use lower caps for the initial character of properties and capitals for the initial character of classes and values. Also, use singular for all product classes rather than plural ("TV set" instead of "TV sets", and start property names with "has" ("hasScreenSize" instead of "screenSize").

1. Define all classes of products and services types that you need.

Example: TVSet, !ComputerMouse, Apartment

2. Collect all relevant properties (typical product features) for each class:

Example:

  • TVSet: hasScreenSize, hasVideoInput, hasOperatingVoltage
  • ComputerMouse:hasInterface, hasWeight, hasBrandname
  • Apartment: hasSize, hasKitchen

3. Determine for all properties which type of property they are, i.e.

  • datatypeProductOrServiceProperty,
  • qualitativeProductOrServiceProperty, or
  • quantitativeProductOrServiceProperty.

Also, determine the proper range for each property.

Example:

  • TVSet:
    • hasScreenSize is a quantitativeProductOrServiceProperty of type float (with a typical Unit of Measurement inches or centimeters, but that's not important here)
    • hasVideoInput is a datatypeProductOrServiceProperty of type boolean (yes/no)
    • hasOperatingVoltage is a quantitativeProductOrServiceProperty of type integer or float (with a typical Unit of Measurement volts, but that's not important here)
  • ComputerMouse:
    • hasInterface is a qualitativeProductOrServiceProperty of a special value type "InterfaceType", which we will have to define unless it exists already
    • hasWeight is a quantitativeProductOrServiceProperty of type float (with a typical Unit of Measurement grams, but that's not important here)
    • hasBrandname is a datatypeProductOrServiceProperty of type string(text)
  • Apartment:
    • hasSize is a quantitativeProductOrServiceProperty of type float (with a typical Unit of Measurement sqft or squaremeters, but that's not important here)
    • hasKitchen is a datatypeProductOrServiceProperty of type boolean (yes/no)

4. For all value types that have to be defined for qualitativeProductOrServiceProperties, define a suitable class and collect all relevant values as instances:

Example: We have to define a class for the special value type "InterfaceType"and instances thereof like "USB", "PS2", and "RS232", reflecting typical interface types.

Note: GoodRelations supports multiple units of measurements for quantitative properties. You do not need to and should not define the intended unit of measurement as part of the property. If you want users to employ only a single unit, add a respective recommendation in the textual description of the property.

Conceptual Structure

Click to enlarge.

thumb\|center\|700px

Ontology Coding

Now, create the OWL ontology using a tool of your choice by using the following procedure:

1. Create a new OWL ontology file.

2. Import the GoodRelations ontology from <http://purl.org/goodrelations/v1>

3. Define a namespace prefix "gr:" for "http://purl.org/goodrelations/v1#"

4. Create one owl:Class for each class of product or service, and make each class an rdfs:subClassOf gr:ProductOrService

Example:

  • ex:TVSet rdf:type owl:Class
  • ex:TVSet rdfs:subClassOf gr:ProductOrService
  • ex:ComputerMouse rdf:type owl:Class
  • ex:ComputerMouse rdfs:subClassOf gr:ProductOrService
  • ex:Apartment rdf:type owl:Class
  • ex:Apartment rdfs:subClassOf gr:ProductOrService

5. Create respective properties for each of your product properties using the following schema

a) For a datatypeProductOrServiceProperty, create an owl:DatatypeProperty and make it an rdfs:subPropertyOf gr:datatypeProductOrServiceProperty

b) For a qualitativeProductOrServiceProperty, create an owl:ObjectProperty and make it an rdfs:subPropertyOf gr:qualitativeProductOrServiceProperty

c) For a quantitativeProductOrServiceProperty, create an owl:ObjectProperty (!!!) and make it an rdfs:subPropertyOf gr:quantitativeProductOrServiceProperty

Example:

  • ex:hasInterface rdf:type owl:ObjectProperty
  • ex:hasInterface rdfs:subPropertyOf gr:qualitativeProductOrServiceProperty
  • ex:hasWeight rdf:type owl:ObjectProperty
  • ex:hasWeight rdfs:subPropertyOf gr:quantiativeProductOrServiceProperty

6. Create an owl:Class for all value types that you have defined, make it and rdfs:subClassOf gr:QualitativeValue, and create instances thereof for all relevant values

Example:

  • ex:InterfaceType rdf:type owl:Class
  • ex:InterfaceType rdfs:subClassOf gr:QualitativeValue
  • ex:USB rdf:type ex:InterfaceType
  • ex:PS2 rdf:type ex:InterfaceType
  • ex:RS232 rdf:type ex:InterfaceType

7. Specify property ranges properly

For each of your properties, you should define the ranges accordingly. Despite the weird OWL/RDF-S semantics of ranges and domains (see below for details), specifying ranges helps tools suggest suitable values and creating forms for entering data.

Use the following schema:

a) For a datatypeProductOrServiceProperty

  • If the range are single characters or text sequences, use the datatype string.
  • If the range is yes or no, use the datatype boolean.
  • In the rare case that you have property that is clearly qualitative but has numbers as allowed values, us the datatype integer.

Examples are properties like "hasPhoneNumber" or other cases wherre the integer value cannot be understood as a quantity.

Such cases are rather rare, and often the correct modeling choice will be to change the property to quantitativeProductOrServiceProperty (if whart you really model are quantities) or qualitativeProductOrServiceProperty (if what you really model are enumerated values).

b) For a qualitativeProductOrServiceProperty

  • If you have defined a specific class for the set of allowed values, use this class as range.
  • If you did not define a specific class for the set of values, or if multiple sets may apply, simply use gr:QualitativeValue as range

Example: The range of ex:hasInterfaceType is ex:InterfaceType. It could also be simply set to gr:QualitativeValue.

c) For a quantitativeProductOrServiceProperty

  • If the range are floating-point values, use the dataype gr:QuantitativeValueFloat
  • If the range are integer values, use the dataype gr:QuantitativeValueInteger
  • If the range may be integer or floating-point values and you are unable to decide for one (though simply using float is then the better choice), you can use gr:QuantitativeValue for the union of both.

8. Specify property domains if necessary

As for all properties, the domain is by default set to ProductOrService. You can narrow down the domain of one of your properties to a single class or combination of classes. However, this is often hard to achieve, because it requires a very clean taxonomy of goods and still often creates redundancy or nasty inconsistencies. Also, note that the semantics of domains in OWL and RDF-S is inferring additional class membership (!), which usually has unwanted side-effects instead of warning the user of inconsistencies. (In a nutshell, if you define the domain of "hasScreenSize" as "TV Set", and someone applies "hasScreenSize" to a "Window", then the system will assume that the window is also a TV Set, instead of warning or forbidding that usage.)

9. Save your ontology, test it, and publish it!

Recommendations on how to publish your ontology are e.g. given here: http://www.w3.org/TR/swbp-vocab-pub/

Example in RDF/XML

The following is the full code of the example used in this tutorial in RDF/XML.

<!-- Created with Protege (with OWL Plugin 3.3.1, Build 430)  http://protege.stanford.edu -->
<?xml version="1.0"?>
<rdf:RDF
   ns="http://www.heppnetz.de/ontologies/examples/toy#"
   xmlns:protege="http://protege.stanford.edu/plugins/owl/protege#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
   xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
   xmlns:owl="http://www.w3.org/2002/07/owl#"
   xmlns:gr="http://purl.org/goodrelations/v1#"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xml:base="http://www.heppnetz.de/ontologies/examples/toy">
<owl:Ontology rdf:about="">
   <dc:rights rdf:datatype="http://www.w3.org/2001/XMLSchema#string">
      This toy ontology is available under the Creative Commons Attribution 3.0 license;
      see http://creativecommons.org/licenses/by/3.0/.
   </dc:rights>
   <owl:imports rdf:resource="http://purl.org/goodrelations/v1"/>
   <dc:creator rdf:datatype="http://www.w3.org/2001/XMLSchema#string">
     Martin Hepp, http://www.heppnetz.de
   </dc:creator>
</owl:Ontology>
<owl:Class rdf:ID="Apartment">
   <rdfs:subClassOf rdf:resource="http://purl.org/goodrelations/v1#ProductOrService"/>
</owl:Class>
<owl:Class rdf:ID="TVSet">
   <rdfs:subClassOf rdf:resource="http://purl.org/goodrelations/v1#ProductOrService"/>
</owl:Class>
<owl:Class rdf:ID="ComputerMouse">
   <rdfs:subClassOf rdf:resource="http://purl.org/goodrelations/v1#ProductOrService"/>
</owl:Class>
<owl:Class rdf:ID="InterfaceType">
   <rdfs:subClassOf rdf:resource="http://purl.org/goodrelations/v1#QualitativeValue"/>
</owl:Class>
<owl:ObjectProperty rdf:ID="hasOperatingValue">
   <rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#quantitativeProductOrServiceProperty"/>
   <rdfs:domain rdf:resource="#TVSet"/>
   <rdfs:range rdf:resource="http://purl.org/goodrelations/v1#QuantitativeValueInteger"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="hasWeight">
   <rdfs:domain rdf:resource="#ComputerMouse"/>
   <rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#quantitativeProductOrServiceProperty"/>
   <rdfs:range rdf:resource="http://purl.org/goodrelations/v1#QuantitativeValueFloat"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="hasScreenSize">
   <rdfs:domain rdf:resource="#TVSet"/>
   <rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#quantitativeProductOrServiceProperty"/>
   <rdfs:range rdf:resource="http://purl.org/goodrelations/v1#QuantitativeValueFloat"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="hasSize">
   <rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#quantitativeProductOrServiceProperty"/>
   <rdfs:range rdf:resource="http://purl.org/goodrelations/v1#QuantitativeValueFloat"/>
   <rdfs:domain rdf:resource="#Apartment"/>
</owl:ObjectProperty>
<owl:ObjectProperty rdf:ID="hasInterface">
   <rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#qualitativeProductOrServiceProperty"/>
   <rdfs:domain rdf:resource="#ComputerMouse"/>
   <rdfs:range rdf:resource="#InterfaceType"/>
</owl:ObjectProperty>
<owl:DatatypeProperty rdf:ID="hasVideoInput">
   <rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#datatypeProductOrServiceProperty"/>
   <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#boolean"/>
   <rdfs:domain rdf:resource="#TVSet"/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID="hasKitchen">
   <rdfs:domain rdf:resource="#Apartment"/>
   <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#boolean"/>
   <rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#datatypeProductOrServiceProperty"/>
</owl:DatatypeProperty>
<owl:DatatypeProperty rdf:ID="hasBrandname">
   <rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#string"/>
   <rdfs:domain rdf:resource="#ComputerMouse"/>
   <rdfs:subPropertyOf rdf:resource="http://purl.org/goodrelations/v1#datatypeProductOrServiceProperty"/>
</owl:DatatypeProperty>
<InterfaceType rdf:ID="PS2"/>
<InterfaceType rdf:ID="RS232"/>
<InterfaceType rdf:ID="USB"/>
</rdf:RDF>
<!-- Created with Protege (with OWL Plugin 3.3.1, Build 430)  http://protege.stanford.edu -->

Example in N3 Notation

The following is the full code of the example used in this tutorial in N3 Notation. Note: In a real case, you should add rdfs:label and rdfs:comment properties to all conceptual elements.

# Base: http://www.heppnetz.de/ontologies/examples/toy#
@prefix gr: <http://purl.org/goodrelations/v1#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix default: <http://www.heppnetz.de/ontologies/examples/toy#> .
@prefix protege: <http://protege.stanford.edu/plugins/owl/protege#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .

<http://www.heppnetz.de/ontologies/examples/toy>
    a owl:Ontology ;
    rdfs:label "Toy ontology"@en;
    dc:creator "Martin Hepp, http://www.heppnetz.de";
    dc:rights """This toy ontology is available under the Creative Commons Attribution 3.0
 license; see http://creativecommons.org/licenses/by/3.0/."""@en ;
    owl:imports <http://purl.org/goodrelations/v1> .

# Classes for types of products
default:Apartment
    a owl:Class ;
    rdfs:subClassOf gr:ProductOrService .

default:ComputerMouse
    a owl:Class ;
    rdfs:subClassOf gr:ProductOrService .

default:TVSet
    a owl:Class ;
    rdfs:subClassOf gr:ProductOrService .

# Properties
default:hasOperatingValue
    a owl:ObjectProperty ;
    rdfs:domain default:TVSet ;
    rdfs:range gr:QuantitativeValueInteger ;
    rdfs:subPropertyOf gr:quantitativeProductOrServiceProperty .

default:hasVideoInput
    a owl:DatatypeProperty ;
    rdfs:domain default:TVSet ;
    rdfs:range xsd:boolean ;
    rdfs:subPropertyOf gr:datatypeProductOrServiceProperty .

default:hasKitchen
    a owl:DatatypeProperty ;
    rdfs:domain default:Apartment ;
    rdfs:range xsd:boolean ;
    rdfs:subPropertyOf gr:datatypeProductOrServiceProperty .

default:hasWeight
    a owl:ObjectProperty ;
    rdfs:domain default:ComputerMouse ;
    rdfs:range gr:QuantitativeValueFloat ;
    rdfs:subPropertyOf gr:quantitativeProductOrServiceProperty .

default:hasSize
    a owl:ObjectProperty ;
    rdfs:domain default:Apartment ;
    rdfs:range gr:QuantitativeValueFloat ;
    rdfs:subPropertyOf gr:quantitativeProductOrServiceProperty .

default:hasScreenSize
    a owl:ObjectProperty ;
    rdfs:domain default:TVSet ;
    rdfs:range gr:QuantitativeValueFloat ;
    rdfs:subPropertyOf gr:quantitativeProductOrServiceProperty .

default:hasInterface
    a owl:ObjectProperty ;
    rdfs:domain default:ComputerMouse ;
    rdfs:range default:InterfaceType ;
    rdfs:subPropertyOf gr:qualitativeProductOrServiceProperty .

default:hasBrandname
    a owl:DatatypeProperty ;
    rdfs:domain default:ComputerMouse ;
    rdfs:range xsd:string ;
    rdfs:subPropertyOf gr:datatypeProductOrServiceProperty .

# Value classes and their instances
default:InterfaceType
    a owl:Class ;
    rdfs:subClassOf gr:QualitativeValue .

default:PS2
    a default:InterfaceType .

default:RS232
    a default:InterfaceType .

default:USB
    a default:InterfaceType .

Extensions directly in RDFa

You can always extend GoodRelations in your own namespace if you need additional properties. There is no need to wait for us to add new elements if you have more data or more granular data. Simply define the additional elements in your own site, ideally directly in RDFa in a special "vocabulary" page, e.g.

For instance, for adding a new property "hasNACE" to the gr:BusinessEntity class, it is sufficient to add this block of markup to your http://acme.com/vocabulary/ page:

<!-- Example of extending GoodRelations with site-specific properties
Step 1: Define a new property; this should be on a central page
e.g. http://acme.com/vocabulary/  -->

<div typeof="owl:DatatypeProperty"
    about="http://acme.com/vocabulary/#hasNACE">
 <span property="rdfs:label">hasNACE</span>
 <div rel="rdfs:domain"
       resource="http://purl.org/goodrelations/v1#BusinessEntity"></div>
 <div rel="rdfs:range"
      resource="http://www.w3.org/2001/XMLSchema#string"></div>
</div>

Then, you can use the property anywhere on your site or even globally. E.g. you could use it in the markup of your main page:

<!-- Attach it to a company -->
<div xmlns:acme="http://acme.com/vocabulary/#" typeof="gr:BusinessEntity" about="#company">
 <span property="gr:legalName">ACME Inc.</span>
 NACE code:
 <div property="acme:hasNACE" datatype="xsd:string">0123456</div>
</div>

If the extensions are new properties or new classes for types of products or services, your modeling pattern should follow the recipe shown here:

That means that for those properties, you will have to make the properties and classes specializations of the meta-model from GoodRelations, i.e.

  • gr:datatypeProductOrServiceProperty,
  • gr:quantitativeProductOrServiceProperty,
  • gr:qualitativeProductOrServiceProperty,
  • gr:ProductOrService, or
  • gr:QualitativeValue

Example: We want to define a new property hasWifi for indicating Wifi support of a product. The range will be a boolean value, so following from the extensions recipe, it must be an owl:DatatypeProperty and an rdfs:subPropertyOf gr:datatypeProductOrServiceProperty.

On the vocabulary page, we define a new product property:

<div typeof="owl:DatatypeProperty"
     about="http://acme.com/vocabulary/#hasWifi">
  <div rel="rdfs:subPropertyOf"
    resource="http://purl.org/goodrelations/v1#datatypeProductOrServiceProperty"></div>
  <span property="rdfs:label">hasWifi</span>
  <div rel="rdfs:domain"
        resource="http://purl.org/goodrelations/v1#ProductOrService"></div>
  <div rel="rdfs:range"
       resource="http://www.w3.org/2001/XMLSchema#boolean"></div>
</div>

Then, we can use it on item pages with the full property URI or by defining a namespace prefix for our site:

<!-- Attach it to a product datasheet -->
<div xmlns:acme="http://acme.com/vocabulary/#" typeof="gr:ProductOrServiceModel" about="#product">
  <span property="gr:name">ACME Anvil with Wifi</span>
  Wifi:
  <div property="acme:hasWifi" content="true" datatype="xsd:boolean">yes</div>
</div>