Skip to content

Ontologies (Details)

ShahzadAmeen edited this page Aug 5, 2018 · 16 revisions

Table of Contents

Introduction

The universAAL platform makes extensive use of ontologies and of the related standards RDF and OWL. The whole topic is quite comprehensive and we will thus try to limit the details to those basic concepts that are needed to understand and use the platform components as described in the following chapters. Still, this chapter is a bit on the theoretical side, so bear with us: real source code writing action awaits just around the corner.

Besides explaining what ontologies are, how they are required for universAAL-based applications, this chapter also points out how you can manually create new ontologies (should that be a necessity). Note, however, that although this can be done by hand, we would rather suggest that you use the universAAL tools to create your own ontology project, to model the required classes as UML diagrams and to then have the whole of it automatically transformed to Java classes. The chapter about the Transformation Tool explains how this works.

There are a lot of sources in the Internet about ontologies, e.g.

To bring the semantic platform universAAL to its full potential, it is recommended to delve more into this topic, read some of the external tutorials, and look at the ontologies already available. However, the following chapter tries to provide some basic information, the representation and the usage of ontologies in universAAL.

Mom, what's an Ontology?

First of, let me rephrase that question for you: what do we need ontologies for? The reason why ontologies were introduced to the area of computer science by the American computer scientist Tom Gruber (the same guy that went on to invent Apple's Siri technology) is to help solve the problem of how to make computers "understand", what they are doing. Originally, the term ontology came from the area of philosophy, but it is used rather differently in computer science. Here, an ontology is an "explicit specification of a conceptualization" (quoting Gruber), or, in simpler terms, a model of a specific part of the real world such that the information contained within this model can be processed by computers. Indeed, such an ontology can be used to represent all sorts of information: a company's personnel structure, the evolutionary tree of mammals, or the construction plans of your car. For now, it may help you to think of an UML diagram or a Java class hierarchy for the purpose of understanding, what ontologies are. Indeed, both UML and Java are well suited for modeling ontologies and we will get back to the relation between ontologies and Java class hierarchies in a bit.

In principle, ontologies can be used to serve two purposes. For one, they are suited for distributing knowledge between two or more applications. Consider the phrase "it's 27 degrees in the living room right now". If spoken to you by a friend, chances are good that you get her point. The reason for this is, however, that you can automatically fill in the blanks in the statement, and thus make it unambiguously. You know which room of the house is the living room she is referring to, you know that by saying "27 degrees", she means "27 degrees Celsius". You also know that this is not comfortable and you know that, because "right now" is 9 p.m. in early August, this is going to be a warm summer night. All of these additional bits of information are available to you because the knowledge that is contained in your friend's statement fits into your inner model of the world around you. Now, consider the very same statement if exchanged between applications. If an application that controls a temperature sensor located in the living room broadcasts the statement "it's 27 degrees in the living room right now" to all other running applications in the system, the best way to make sure that these other applications understand the right thing is to use a common ontology. This is a model of the real world that states, among other things, that, by human standards, 27 degrees is a bit too warm to be considered comfortable. In the universAAL world, we call this kind of information "contextual information" and we use the so-called Context Bus to distribute this contextual information among the nodes of the system. You will learn how to use the Context Bus in the chapter Context-Bus-(Details).

Besides knowledge sharing, the second reason why we need ontologies in computer science is for the sharing of functionalities. Think of an application that controls various light sources, among which is a lamp in the apartment's bedroom. Now think of another application that sends a request to all running applications, asking them to turn off the light sources in bedroom. Note that this second application does not call specific methods of specific applications. It just "asks" everyone available to perform a service if capable of doing so. And because our first application "knows" that it controls a lamp in the bedroom, it turns it off and sends a notification to the requester ("turned off the lamp I control"). This kind of behavior can be realized using ontologies, allowing applications to access the functionalities of other applications not by using predefined syntactic interfaces (such as myLampController.TurnOffLights("LivingRoom")), but rather by way of formulating more generic, semantic requests. Through this, an assistive system can achieve a much higher degree of autonomy than by having to manage with only a few, hard-coded interfaces. Systems based on the universAAL platform use the platform's Service Bus for the purpose of sharing functionalities. You will learn how to use the Service Bus in the chapter Service-Bus-(Details) of this documentation.

Representing Ontological Models

Ontological models can be represented using a variety of different formalisms. The aforementioned RDF/OWL standard has risen to become the gold standard way of representing ontologies in computer science and because of that, the formalism used within the universAAL project is heavily based on RDF. However, ontologies can also be modeled using any other method, as long as it is capable of capturing the same degree of information as RDF. One such method are Java class hierarchies and because we assume that most of our readers are familiar with Java, we will use this method to explain the concepts of ontological models in more detail. Conveniently, Java classes are also used to model ontologies in universAAL, so once you understood how ontologies relate to Java class hierarchies, you have taken a huge steps towards creating your first own universAAL ontology.

Starting with the very basics, ontologies in universAAL are made up of three entities: data types, classes, and properties. The latter are used for specifying the relationships between two classes or between a class and a data type. A special kind of relation between the class entities is "inheritance", which works exactly as in Java (a class inherits all properties from its parent class). Let's say we want to create an ontology that states what light sources are, what they do, and how the different types of light sources relate to each other. The process of creating such an ontology is very similar to how one would create a Java class hierarchy. Starting with the topmost class "LightSource", one would then derive the more specialized classes from this super class, such as "BeamingSource" or "BlinkableLightSource". Figure 1 shows an overview. The superclass "LightSource" should have a property "brightness", which states that all light sources generate some sort of the same. To reflect the fact that the same light source can generate different levels of brightness (especially the dimmable ones), we would not want this property to be a boolean but rather an integer value, ranging from 0 (for "off") to 100 (for "maximum capacity"). The values in between would then represent a certain percentage of dimming. While we are on it, let's think of other properties a light source model could have. A second property we might want to consider adding is one to specify the light sources type (such as "flaming", "natural" or "electric"). Each of these types is a new ontological class of its own. As a third property, we will also add "ambientCoverage", which specifies the area that is being illuminated by the light source. This value is of type "Location", which is another ontological class and this connects our light source ontology to another ontology (namely the one that defines, what locations are). Through this, we can link our small model of a very specific aspect of the world to another model, thus creating increasingly complex models of the world. In universAAL, most ontologies you manually create will probably be linked (one way or the other) to the "Physical World Ontology". This ontology is part of the platform core and defines very basic concepts such as what a "PhysicalThing" is, or a "Location".

At this point, you are probably wondering for what the difference between an ontology and a set of ordinary Java classes is. The main difference is that Java classes are meant to be dynamic, while ontologies are static. When you create a Java class, you (usually) also create a set of methods that go with this class. These methods accept parameters, perform some sort of calculation and many of them return a return value. And when you create instances of your classes, they can call these methods and thus transform information (from the input parameters) into other information (contained in the return value). This is not the case for ontologies, which are used to represent knowledge. There is no dynamic part in this, the ontological classes are a model and the instances of this model are called "facts". The name itself implies that these will not change. As an example for such a fact, consider the triple (LivingRoomLamp, brightness, 100). The information contained within this "fact" is that the LightSource "LivingRoomLamp" has full brightness. This information holds true at the time of the fact's creation and this will not change. In case you are wondering: the reason why we wrote down the fact the way we did (as a triple) is because this is the way that facts are captured in the RDF world. We will get back to this in a few, but for now, just consider the particular format of the fact (LivingRoomLamp, brightness, 100). It starts with an instance of an ontological class (LivingRoomLamp might be an instance of the class LightSource). Next is a property of this instance (brightness), followed by the value of this property, in this case an integer (100). This is the way we will write all facts, that is, how we will capture contextual information. It's always a triple of a subject, followed by a predicate, followed by an object (which represents the predicate's value).

Coming back to the differences between Java classes and ontologies, another one are naming conventions. While Java classes usually have a simple and ideally also meaningful name (such as "myLightSource"), the point of ontological classes is to unambiguously describe a specific aspect of the world and to make sure, that two communication partners understand a statement (or rather, a fact) in the exact same way. Because of this, we need a method for identifying ontological classes (and their properties) precisely, a sort of a "globally unique identifier". All of us use such a method on a day-by-day basis when browsing the Internet, as every website on the web has an unique URL, its name if you will, and no two websites share the same name. URLs are a type of what computer scientists call Uniform Resource Identifiers, or URIs for short. Using URIs, we can ensure that all parts of our Lighting ontology, all classes and all of their properties, are uniquely identifiable. We can even give a unique name to the whole ontology itself: http://ontology.universaal.org/Lighting.owl. You will encounter the prefix http://ontology.universaal.org at all universAAL-related ontologies. We call this part the "absoluteURI", as it (usually) stays the same through all ontologies you create. The absoluteURI is followed by the "relativeURI", which is just a slash followed by the name of your ontology (such as "/Lighting.owl" in case of the lighting ontology). Combined, absoluteURI and relativeURI make up the unique identifier of your ontology - its namespace. As long as no other universAAL developer uses the same name for her ontology (which you will notice the latest when you try to compile your universAAL-based applications), this identifier is globally unique and all applications that rely on your ontology can thus be sure to "mean the same thing". In order to provide a specific ontological class with its own URIs (which is required), you extend the ontology URI (absoluteURI and relativeURI) by the delimiter "#", followed by the name of that class (this part of the URI is called "the fragment"). Doing this, you will end up with class URIs such as these:

Of course, we could also use other unique identifiers (such as 256 bit random numbers), but the approach as described above has two huge advantages. First of, the name is meaningful (you know right away that the URI http://ontology.universaal.org/Lighting.owl#LightSource refers to an ontological class named "LightSource" within the "Lighting ontology", which is part of the universAAL ontology). And in addition, a documentation for this specific ontology can be uploaded to this specific web address (simply contact an universAAL administrator if you would like to have your own documentation uploaded).

A Taste of RDF

We have already mentioned that for universAAL, we rely on the RDF standard to write down ontological information. A "RDF statement" is a triple of a subject, followed by a predicate, followed by an object, with the subject being a resource and the object being either a resource or a data value. A resource is anything that has an unique URI attached to it, in our case ontological classes (and their instances). Recall the fact (LivingRoomLamp, brightness, 100) and you will notice that this is a RDF statement, as it starts with a resource (LivingRoomLamp is an instance of the ontological class LightSource), followed by a predicate (brightness is a property of the ontological class LightSource), followed by the integer value "100", which is a data value. Multiple of these statements can be linked to each other by using resources as objects. These resources, being the object of one statement, then become the subject of another statement.

Before we go into more detail, let us quickly try to point out the differences between the two terms RDF and OWL, that we have been using largely synonymously up to here. RDF is a method for describing uniquely identifiable resources by using the aforementioned RDF-statements. OWL is often said to be an extension of RDF, but that is not really correct. OWL is rather a concept of its own, used for describing the properties of ontologies. OWL just builds upon the RDF-schema for describing resources because it has established itself so well. Any information, that is displayed in the "OWL language" can also be displayed using the "RDF language", and vice versa. The difference between the two is that OWL also includes the concept of "that information makes sense", which RDF lacks. This, in turn, allows for "inference", that is the combination of facts (= of information that makes sense) to produce additional facts.

Back to RDF. The RDF-representation as pointed out above is adopted in universAAL: the Java class "Resource" corresponds to an RDF resource and every ontological class is a subclass of it (to be more precise: ontology classes are subclasses of "ManagedIndividual" which is a subclass of "Resource"). As the capabilities of resources are very restricted (a resource describes something that is identified by a URI), some information must be coded in multiple RDF statements. Most notably is the type information. In our statement above we have the resource "LivingRoomLamp" which may or may not be an easily interpretable String, so it may be possible to derive the type (LightSource) from it, but generally an instance URI like this is a String with the sole property of being unique. Hence, it is necessary to include some sort of type information about it. This is typically realized by adding additional statements like (LivingRoomLamp, rdf:type, LightSource).

Most of the RDF representation is done automatically and developers do not have to take care of it. The Java classes in universAAL that represent ontology classes mostly consist of simple getter and setter methods:

 public class LightSource extends PhysicalThing {
     public static final String MY_URI = LightingOntology.NAMESPACE + "LightSource";
     public static final String PROP_AMBIENT_COVERAGE = LightingOntology.NAMESPACE + "ambientCoverage";
     public static final String PROP_HAS_TYPE = LightingOntology.NAMESPACE + "hasType";
     public static final String PROP_SOURCE_BRIGHTNESS = LightingOntology.NAMESPACE + "srcBrightness";
 
     public LightSource(String uri) {
         super(uri);
     }
     
     public String getClassURI() {
         return MY_URI;
     }
 
     public int getBrightness() {
         Integer i = (Integer) getProperty(PROP_SOURCE_BRIGHTNESS);
         return (i == null) ? -1 : i.intValue();
     }
 
     public void setBrightness(int percentage) {
         if (percentage > -1 && percentage < 101)
             setProperty(PROP_SOURCE_BRIGHTNESS, new Integer(percentage));
     }
     ...
 }
This code snippet is a slightly modified version compared to the one you can find in the ontologies GIT repository. However, the basic concepts should be clear: "LightSource" is both Java and ontology class identified by "LightSource.MY_URI". It defines some properties in form of URIs and provides get/set methods for the brightness which mainly call the getProperty/setProperty methods of the super class Resource. The type information is automatically added (the super class "ManagedIndividual" calls setProperty(rdf:type, getClassURI())). In OWL, instances of ontological classes are called individuals, e.g. the LivingRoomLamp from our example would be an individual of the class LightSource.

Type Expressions

So far, we have seen how ontological classes are made available in universAAL. The question is now: why do we need this? Ontologies are a general model of something and can be treated as shared knowledge since typically the ontologies are available on all universAAL nodes (or at least on the nodes that need them). The basic idea is, that the nodes can understand each other when the information is modelled in a unified way; and the messages that are exchanged between components basically are RDF graphs. For example, the Context Bus uses Context Events that some provider publishes on the Context Bus. A Context Event could be "the lamp in the living room is turned on" which would be expressed in form of an RDF graph as described above. The main advantage is now that a component interested in a specific set of Context Events can describe that specific set in form of OWL expressions which pose descriptions and restrictions on the incoming RDF graph, so that only the events of interest are delivered to the so-called context consumer.

The Service Bus works similar: all services register themselves at the Service Bus by providing a set of service profiles which are represented as RDF graphs. When another component wants to call a certain service, it provides a description of the RDF graph for the service it wants to invoke. The bus then finds and calls the appropriate service. To realize this, OWL offers a quite extensive set of "type expressions" to describe RDF graphs (note that OWL actually distinguishes between class expressions to describe classes and data ranges to describe data types, but for the sake of simplicity in universAAL, both are derived from a class called TypeExpression). The following Figure depicts an overview over all type expressions in universAAL.

From OOP languages we know the concept of classes and their instances. For example, you can create Class1 and Class2 and both have an integer variable called brightness. When we create instances of these two classes then both have this integer variable, but we cannot say that we want all objects that have this integer because they are instances of different classes. In OWL, this is possible: we can create a new class simply by describing all instances of it!

When we want to describe an RDF graph, there are basically three possibilities:

  1. a node
    • use Enumeration for a set of concrete instances (individuals or literals), e.g.
      new Enumeration(new Resource[] {new Resource("LivingRoomLamp")}) for the resource LivingRoomLamp or
      new Enumeration(new Integer[] {new Integer(0), new Integer(100)}) for the integer values 0 and 100
    • use TypeURI for a specific class/data type, i.e. all instances of a specific ontological class/data type, e.g.
      new TypeURI(LightSource.MY_URI, false) for all instances of LightSource or
      new TypeURI(TypeMapper.getDatatypeURI(Boolean.class), true) for all instances of Boolean
    • use set-theoretic operations Intersection, Union, Complement; in logical languages these are usually called conjunction, disjunction, and negation, respectively
  2. a property of a node
    describing the property itself can only be done by giving the cardinality, i.e. to how many nodes this node is connected by the given property: MinCardinalityRestriction, MaxCardinalityRestriction, or ExactCardinalityRestriction (when min=max)
  3. an adjacent node (the node of interest is connected to that node by a certain property)
    • use HasValueRestriction for a concrete individual or literal
    • use BoundedValueRestriction for a concrete literal that lies within the given bounds (min value and/or max value). Use the subclasses for a specific type, e.g. IntRestriction, FloatRestriction
    • use AllValuesFromRestriction to define that the individual/literal (if any) is an instance of the given type expression
    • use SomeValuesFromRestriction if there exists at least one instance of the given type expression
    • use MergedRestriction to combine multiple single restrictions for the same property. Most methods in universAAL take a MergedRestriction as parameter (or have it as return value). MergedRestriction also provides some static helper methods to e.g. create a MergedRestriction and add an AllValuesFromRestriction and cardinality restrictions with just one method call:
      MergedRestriction.getAllValuesRestrictionWithCardinality(String propURI, String typeURI, int min, int max).
Type expression can be cascaded with AllValuesFromRestriction or SomeValuesFromRestriction: if you have a property path (a list of properties that determine a path through the RDF graph), then you can specify descriptive information about all resources and properties along that path. Thus, you specify the set/class of all individuals that are connected by the property path to some set of individuals or literals, and all resources and properties along that path must fulfill the given restrictions. To be more precise: you can also define restrictions along a property graph! For example, if you have the following graph:
 LightSource  --brightness-->  Integer
              --hasLocation-->  Room  --adjacentTo-->  Room

If you want all light sources (i.e. all individuals of LightSource) that have the brightness 100 and are in a location (a Room is a subclass of Location) that is adjacent to the "LivingRoom", you can specify the following type expression:

 Intersection(
    TypeURI(LightSource.MY_URI),
    HasValueRestriction(brightness, 100^Integer),
    SomeValuesFromRestriction(hasLocation,
       Intersection(
          TypeURI(Room.MY_URI),
          HasValueRestriction(adjacentTo, "LivingRoom") ) ) )

Type Expressions are explained in more detail in the data representation model of the middleware.

How to create your own Ontology

We will now explain, how you can manually create your own ontologies in case none of the provided ones suits your needs. Note that this section is a bit more advanced than the previous ones - if you are new to the universAAL world, chances are that you won't have to create a custom ontology for quite a bit. But if you do, keep in mind that the universAAL project also has tools available that can support you in the process - see Transformation Tool for the details.

All classes from the ontology are implemented in Java by creating a subclass of ManagedIndividual (an example is given for the class LightSoure in the code snippet shown above). It does not necessarily have to be a direct subclass, so you can decide from which class you actually derive. You should keep in mind that in OWL, multiple inheritance is possible; in universAAL this is handled by managing the inheritance information separately, i.e., for each class you have to specify manually its super class.

So, what about ontologies? The overall picture looks like this: the class Ontology corresponds to the concept of an OWL ontology and contains all ontological information of one ontology (OWL classes, properties, special individuals, ...). You have to create a subclass of Ontology and add all these information. Ontologies are then registered at the OntologyManagement (that follows the Singleton Design Pattern) which provides a global view on all ontologies and all ontological information of the system, i.e., on the information of all ontologies. If multiple ontologies provide information about the same concept, e.g., a concept is defined in one ontology and refined in another ontology, then the ontology management provides a combined view on these two ontologies. This is important for ontology alignment and mapping.

To create an ontology, you have to create a subclass of Ontology and overwrite its create() method where you provide some general information about the ontology itself (like comment, label, and the set of URIs of the imported ontologies) and about its elements (classes, properties, ..). As mentioned above, there is a corresponding instance of OntClassInfo for each ontological class. The class Ontology provides four protected methods to create such an information class:

 createNewAbstractOntClassInfo(String classURI)
 createNewOntClassInfo(String classURI, ResourceFactory fac)
 createNewOntClassInfo(String classURI, ResourceFactory fac, int factoryIndex)
 extendExistingOntClassInfo(String classURI)
The first three methods are meant to define a new ontological class. For de-/serialization of these classes, a factory (according to the factory design pattern) is used and an additional index can be provided to ease the selection of the class that needs to be created. So, you can use the same factory to create instances of different classes according to the index specified here. If you do not provide a factory for a class, then this class is treated as an abstract class. A factory can look like this:
 public class MyOntologyFactory implements ResourceFactory {
    public Resource createInstance(String classURI, String instanceURI, int factoryIndex) {
       switch (factoryIndex) {
          case 1:
             return new OntClass1(instanceURI);
          case 2:
             return new OntClass2(instanceURI);
          ...
       }
    }
 }
The fourth and last method is extendExistingOntClassInfo, which does not define a new class, but is intended to provide additional information about an existing ontological class (e.g. for ontology mapping). Normally, an ontological class is defined exactly once but can be extended multiple times.

The return value of these four methods is the interface OntClassInfoSetup which offers a variety of different setter methods, e.g. to specifiy the super class by giving its URI, or to specify properties and their restrictions.

When all information are provided, the ontology needs to be registered at the ontology management. This is typically done at starting time of the module (and, of course, it is unregistered when the module is stopped), so:

 public class Activator implements ModuleActivator {
    MyOntology ont = new MyOntology();
    
    public void start(ModuleContext context) throws Exception {
       OntologyManagement.getInstance().register(context, ont);
    }
    
    public void stop(ModuleContext context) throws Exception {
       OntologyManagement.getInstance().unregister(context, ont);
    }
 }
Thus, for one OWL class you typically have in universAAL:
  • One class derived from ManagedIndividual (which is a subclass of Resource) which basically defines URIs for itself and its properties and offers getter and setter methods for its properties. This class is mainly used by other components.
  • A factory, or an entry in an existing factory, which is used to create new instances of this class, i.e., for deserialisation.
  • An instance of OntClassInfo (and for the creator: OntClassInfoSetup) which provides all ontological information about an OWL class.

An Ontology for the Lighting Application

The source code of the class LightSource has already been described before. Accordingly, all other classes of the lighting ontology are created: by specifying URIs of the class itself and for its properties, and by overwriting the method getClassURI(). Actually, this method is the only method necessary to have, all other methods are just getter and setter methods for the properties for convinience of the developer who uses it. Accordingly, all ontological classes are implemented that way.

To enable deserialisation of instances of these classes, a factory is used:

1.01: public class LightingFactory extends ResourceFactoryImpl {
1.02:     public Resource createInstance(String classURI, String instanceURI, int factoryIndex) {
1.03:        switch (factoryIndex) {
1.04:        case 0:
1.05:           return new LightSource(instanceURI);
1.06:        case 1:
1.07:           return new BeamingSource(instanceURI);
1.08:        case 2:
1.09:           ...
1.10:        }
1.11:     }
1.12:  }
The most important part is the ontology. For every ontology a subclass of Ontology is created as shown in the code snippet below. A namespace is defined in line 2.02 which is used by the ontological classes like LightSource, and the factory as described above is instanciated. The constructor provides the namespace to its super class which removes the trailing '#' (if existent) and uses this as the URI of the ontology. From line 2.09 on the overwritten method create() provides all ontological information about the ontology and its elements. First, some general information about the ontology is specified in the lines 2.10 to 2.15; this will build up the ontology header in a serialised output. The code snippet shows the definition of two classes. The first one (LightType in lines 2.20 - 2.22) is very simple, since this is an abstract class and cannot be instanciated. So, it does not have a factory. Additionally, it has no properties that need to be described.

More complex is the next class (LightSource in lines 2.25 - 2.49) which is not an abstract class and, thus, provides the factory created in line 2.03. The index given here corresponds to the index in the factory at line 1.04 and 1.05. Furthermore, LightSource is a subclass of Device and this information is given in line 2.28. In the remaining lines, four properties are defined and restrictions for them are specified. The other classes of the ontology are specified the same way but this is not shown here.

2.01: public final class LightingOntology extends Ontology {
2.02:     public static final String NAMESPACE = "http://ontology.universaal.org/Lighting.owl#";
2.03:     private static LightingFactory factory = new LightingFactory();;
2.04: 
2.05:     public LightingOntology() {
2.06:         super(NAMESPACE);
2.07:     }
2.08: 
2.09:     public void create() {
2.10:         Resource r = getInfo();
2.11:         r.setResourceComment("The ontology defining the most general concepts dealing with light sources and their control.");
2.12:         r.setResourceLabel("Lighting");
2.13:         addImport(DataRepOntology.NAMESPACE);
2.14:         addImport(ServiceBusOntology.NAMESPACE);
2.15:         addImport(LocationOntology.NAMESPACE);
2.16: 
2.17:         OntClassInfoSetup oci;
2.18: 
2.19:         // load LightType
2.20:         oci = createNewAbstractOntClassInfo(LightType.MY_URI);
2.21:         oci.setResourceComment("The type of a light source");
2.22:         oci.setResourceLabel("Light Type");
2.23: 
2.24:         // load LightSource
2.25:         oci = createNewOntClassInfo(LightSource.MY_URI, factory, 0);
2.26:         oci.setResourceComment("The class of all light sources");
2.27:         oci.setResourceLabel("Light Source");
2.28:         oci.addSuperClass(Device.MY_URI);
2.29:         oci.addObjectProperty(LightSource.PROP_AMBIENT_COVERAGE)
2.30:                 .setFunctional();
2.31:         oci.addObjectProperty(LightSource.PROP_HAS_TYPE).setFunctional();
2.32:         oci.addDatatypeProperty(LightSource.PROP_SOURCE_BRIGHTNESS)
2.33:                 .setFunctional();
2.34:         oci.addObjectProperty(LightSource.PROP_SOURCE_COLOR).setFunctional();
2.35:         oci.addRestriction(MergedRestriction
2.36:                 .getAllValuesRestrictionWithCardinality(
2.37:                         LightSource.PROP_AMBIENT_COVERAGE, Location.MY_URI, 0,
2.38:                         1));
2.39:         oci.addRestriction(MergedRestriction
2.40:                 .getAllValuesRestrictionWithCardinality(
2.41:                         LightSource.PROP_HAS_TYPE, LightType.MY_URI, 1, 1));
2.42:         oci.addRestriction(MergedRestriction
2.43:                 .getAllValuesRestrictionWithCardinality(
2.44:                         LightSource.PROP_SOURCE_BRIGHTNESS,
2.45:                         new IntRestriction(
2.46:                             new Integer(0), true, new Integer(100), true),
2.47:                         1, 1));
2.48:         oci.addRestriction(MergedRestriction.getCardinalityRestriction(
2.49:                 LightSource.PROP_SOURCE_COLOR, 0, 1));
2.50:         ...
2.51:     }
2.52: }
The ontology is registered at the ontology management as described in the previous paragraph (just replace MyOntology with LightingOntology).

Short summary and further reading

We have learned about ontologies and URIs and how to use RDF and OWL to represent them in a way that machine and human can interpret them. After that you have seen how universAAL has realized its data representation model to enable it to work in a compatible way to RDF/OWL. Maybe the most important is the Lighting example where we take a short part out of the provided ontology to explain some general concepts of how to write classes for universAAL ontology. In particular keep in mind to define the properties and their restrictions.

A special tutorial based on example code with focus only on the ontology is also available within the ontology project on GIT at https://github.com/universAAL/samples/tree/master/ont.tutorial. Here you can get a more detailed overview on how to model ontologies in general.

The ontologies defined in universAAL are described in ontologies repository.

The following chapters may use a different ontology to model light sources (or light actuators) as shown in the following Figure that shows a part of the device ontology and its interrelation to some other ontologies (PhThing and Location).

Support:

Found a problem?
  • Report suggestions, missing, outdated or wrong documentation creating an Issue with "documentation" tag
Clone this wiki locally