Bloodbee
Bloodbee

Reputation: 935

Defining classes in ontology, instanciating individuals in namespace

Using Owlready2, how to define classes attached to the ontology (on this base iri: http://example.com/ontology/item/1.1#) and when an individual is created, it would be defined on other iri (like: http://example.com/profile/item/resource/) ?

So if i instanciate a defined class Stuff inheriting owlready2.Thing:

    from owlready2 import *
    from rdflib import URIRef

    onto = get_ontology('http://example.com/ontology/item/1.1#')
    
    class Stuff(Thing):
        namespace = onto
    
    stuff = Stuff(
        name='8gdfb186-fc78-4b9e-95c4-545339d3ce1b',
        namespace='http://example.com/profile/item/resource/'
    )

and then i save the ontology to a new file, it would have something like that:

<?xml version="1.0"?>
<rdf:RDF 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#"
         xml:base="http://www.perfect-memory.com/ontology/item/1.1"
         xmlns="http://www.perfect-memory.com/ontology/item/1.1#">

<owl:Ontology rdf:about="http://example.com/ontology/item/1.1"/>

<owl:Class rdf:about="http://example.com/ontology/item/1.1#Stuff">
  <rdfs:subClassOf rdf:resource="http://www.w3.org/2002/07/owl#Thing"/>
</owl:Class>

<Stuff rdf:about="http://example.com/profile/item/resource/8gdfb186-fc78-4b9e-95c4-545339d3ce1b">
  <rdf:type rdf:resource="http://www.w3.org/2002/07/owl#NamedIndividual"/>
</Stuff>

</rdf:RDF>

BUT, this is quite unfriendly to use, as I generate the iri for my individual outside of anything related to ontology and owlready2. So i would like to do something like that:

stuff = Stuff('http://example.com/profile/item/resource/8gdfb186-fc78-4b9e-95c4-545339d3ce1b')

How could I achieve that?

I tried to overload the __new__ method when instanciating, without success:

from owlready2 import *
from rdflib import URIRef

class Stuff(Thing):
    namespace = onto
    
    def __new__(Class, name=None, namespace=None, is_a=None, **kwargs):
        if name and isinstance(name, URIRef):
            splitted = str(name).rsplit('/', 1)
            if len(splitted) == 2:
                new_namespace = onto.get_namespace(f'{splitted[0]}/')
                obj = Thing.__new__(
                    Class,
                    name=splitted[1],
                    namespace=new_namespace,
                    is_a=is_a,
                    **kwargs
                )
                obj.namespace = new_namespace
                obj.namespace.ontology._base_iri = f'{splitted[0]}/'
                obj.set_name(f'{splitted[1]}')
                return obj
        
        obj = Thing.__new__(
            Class,
            name=name,
            namespace=namespace,
            is_a=is_a,
            **kwargs
        )

        return obj

The new individual iri become: http://example.com/profile/item/resource/http://example.com/profile/item/resource/8gdfb186-fc78-4b9e-95c4-545339d3ce1b - of course that's not what i'm looking for.

Any ideas?

PS : As the owlready2 library is actually looking into all parents classes to generate ancestors for the current owlready2 mapped class, it's not possible to do some inheritance on mixins.

Upvotes: 0

Views: 169

Answers (1)

Bloodbee
Bloodbee

Reputation: 935

With further development and research, I was able to achieve it using an init method overriding the Thing's one like that:

def __init__(self, name=None, namespace=None, is_a=None, **kwargs):
        if name and isinstance(name, URIRef):
            splitted = name.rsplit('/', 1)
            if len(splitted) == 2:
                new_namespace = onto.get_namespace(f'{splitted[0]}/')
                super().__init__(splitted[1], new_namespace, is_a, **kwargs)
        else:
            super().__init__(name, namespace, is_a, **kwargs)

Upvotes: 0

Related Questions