Skip to content

Object ontological Mapping

Martin Ledvinka edited this page Jun 27, 2019 · 7 revisions

Object-ontological mapping (OOM) in JOPA is, much like in JPA, realized via annotations in Java.

The annotations tell JOPA which classes it should consider as entity classes, which of their attributes are persistent and to what ontological properties they are mapped.

The most important annotations in this regard are:

@OWLClass

@OWLClass is placed on a Java class and specifies that this class is a part of the persistence unit metamodel. It has one attribute - iri - whose value maps the class to the corresponding RDFS/OWL class.

@Id

@Id marks field which contains the instance's identifier (IRI in ontological terms). Supported types are String, java.net.URI and java.net.URL.

The identifier can be marked as generated, so that when an instance with an empty identifier is persisted, JOPA will generate the identifier value.

@OWLObjectProperty

@OWLObjectProperty marks Java attributes which reference other objects. In OWL, this corresponds to object properties, which link individuals to other individuals. RDF makes no such distinction.

However, for JOPA, the distinction between @OWLObjectProperty and other kinds of properties (see below) is important. They tell it whether it should expect a literal value (like an integer, String) or a resource's identifier. Therefore, when using RDF-based storage like RDF4J, @OWLObjectProperty should still be used, marking fields whose type is either another entity class or String/java.net.URI/java.net.URL. In case the type is String/URI/URL, JOPA will assume that the intended value is an individual's identifier (this is referred to as plain identifier object property in Javadoc and source code. No other types can be used for fields annotated with @OWLObjectProperty.

The iri attribute represents the property to which the annotated attribute is mapped.

fetch specifies whether the attribute value should be eagerly or lazily loaded (it is supposed to work the same as in JPA). Note that when using data access objects, it is usually better to have the fetch set to eager. Since JOPA currently does not support extended persistence contexts, once the loaded object becomes detached from the persistence context (usually when returned from DAO/service with transactional entity manager), lazily loaded attributes may be null without any way to load them. Defaults to FetchType.LAZY.

cascade whether entity manager operations should be cascaded over this attribute. This works the same way as in cascading in JPA.

@OWLDataProperty

@OWLDataProperty marks a literal-valued field. This corresponds to an OWL datatype property. Again, RDF does not care about this distinction, but JOPA will assume the value to be a literal and treat it as such. The annotated fields should not used Java primitive types but their wrapper equivalents, i.e. Integer for int etc.

The iri attribute represents the property to which the annotated attribute is mapped.

fetch works same as above. It defaults to FetchType.EAGER for data properties.

lexicalForm allows to load the property value into a String regardless of the type of the literal. This functionality, however, has a limitation - such an attribute would be read-only. This is because when the field is a String representing lexical form of the literal, JOPA has no way of knowing what the type of the literal should be when saving it (e.g., on persist, or even on update). Updating could thus lead to unintentional changes in the data. A safer way is thus to prevent modification of such values.

@OWLAnnotationProperty

@OWLAnnotationProperty correspond to OWL annotation properties. The notion is not known in RDF, so when accessing RDF-based storages, this annotation can be ignored and OWLDataProperty used instead. However, when using OWL-based storage (i.e. currently only OWL API), the distinctions between different kinds of properties are significant.

The iri attribute represents the property to which the annotated attribute is mapped.

fetch works same as above. It defaults to FetchType.EAGER for annotation properties.

lexicalForm works the same way as above. If the annotation value is an resource/individual, its identifier is loaded into the attribute. The read-only conditions, however, applies to it as well.

Below is a simple example of a JOPA entity, which makes use of all the aforementioned kinds of properties:

@OWLClass(iri = Vocabulary.s_c_Occurrence)
public class Occurrence {

    @Id
    private URI uri;

    @OWLDataProperty(iri = Vocabulary.s_p_has_key)
    private String key;

    @OWLAnnotationProperty(iri = CommonVocabulary.RDFS_LABEL)
    private String name;

    OWLObjectProperty(iri = Vocabulary.s_p_has_part, fetch = FetchType.EAGER, cascade = {CascadeType.MERGE,
            CascadeType.REMOVE})
    private Set<Event> children;

    // Getters and setters follow
}

Note that currently the property annotations have to be placed on the fields, getter/setter annotations are not supported.

If a field should not persistent, on of the following mechanisms can be used:

  • Field is static
  • Field is transient
  • Field is annotated with @Transient
Clone this wiki locally