Friday, August 10, 2012

Accessing Data Property Range values using Jena Framework

Recently, I'm working with semantic web technologies.. I have built an ontology, and now my task is to parse this ontology and generate individuals for classes..

Jena Framework is quite popular to use for building semantic web applications.. I use it for working with my ontology.. There are many tutorials and example codes on Web, so it is easy to work with Jena. And of course, Jena is an ongoing project, and it's not complete in terms of its methods..

One problem that I encountered with is that getRange() method for data properties is not working properly.. It is ok when you use xsd variables such integer, string and such.. But when you use an enumerated list as data property range, this method returns null..

I realized that this method returns a Class rather than a DataRange type.. So it is possible to iterate over enumerated list values using EnumeratedClass..

Now, I will detail how I solved this problem.. Will take an example from my ontology.. I have a class called, Liver. This class has some data properties, and one of them is, hasMarginType. This property has a value which is one of:

{"irregular"^^string , "lobulated"^^string , "nodular"^^string , "other"^^string , "regular"^^string}


And this is how it looks like in Protege:
Now, let's look at the code for parsing this range values using Jena.

//print Liver class data properties
        ExtendedIterator<OntProperty> it = Liver.listDeclaredProperties();
        while(it.hasNext()){
            OntProperty p = it.next();
            if (p.isDatatypeProperty() && p.getDomain()!=null && p.getRange()!=null){
                pr("Data Property Name: "+ p.getLocalName());
                pr("Domain: "+ p.getDomain().getLocalName());
               
                EnumeratedClass e = null;
                ExtendedIterator<RDFNode> i = null;
                if(p.getRange().asClass().isEnumeratedClass()){
                    e = p.getRange().asClass().asEnumeratedClass();
                    i = e.getOneOf().iterator();
                   
                    RDFNode prop = null;
                    String s=null;
                    pr("Range: ");
                    while(i.hasNext()){
                        prop = i.next();
                        s=prop.asLiteral().toString().split("\\^\\^")[0];
                        pr(s);
                    }
                }else{
                    pr("Range: "+ p.getRange().getLocalName());
                }
               
                pr("\n");
            }
           
        }


 This code prints name of a data property, domain of this data property and range value for this data property. Note that pr is a function used to print data on console. My focus was not having the namespaces, thus my output is like this:

Data Property Name: hasMarginType
Domain: Liver
Range:
irregular
lobulated
nodular
other
regular


I did not find a code snippet to work with.. So here it is my solution.. Hope it helps..

3 comments:

Rodrigo said...

This is exactly what I was looking for, i.e., how to express data property range with enum type and to get it using Jena! Perfect!

And your explanation about it is very nice =) Good job!

Rodrigo said...

This is exactly what I was looking for, i.e., how to express data property range with enum type and to get it using Jena! Perfect!

And your explanation about it is very nice =) Good job!

Anonymous said...

This is extremely helpful!!! I was annoyed by this problem for several months.