Question

For a GeoSPARQL test project I want to have a custom datatype set in Jena. Howerver when I try this through the example provided at the Jena website, it still doesn't work. I get the following result:

_:b0 <http://www.opengis.net/ont/geosparql#asWKT> "POINT (52.83525867111958 6.870789811954563)^^http://www.opengis.net/ont/sf#wktLiteral "^^<java:com.hp.hpl.jena.rdf.model.impl.LiteralImpl> .

And of course I don't want the java:com.hp.hpl.jena.rdf.model.impl.LiteralImpl but http://www.opengis.net/ont/sf#wktLiteral because I wan to work with GeoSPARQL. On this page they have example data that works perfectly with my triple store and spatial index. But the above data doesn't work at all with spatial indexing.

So, my question is, I do I define a custom datatype in my RDF in Jena?

Was it helpful?

Solution 2

I just found the answer to my question after a lot of trial and error. To add a custom RDFDatatype to my RDF model I first had to create my own class which extends BaseDatetype and which I called WktLiteral, looking like this:

public class WktLiteral extends BaseDatatype {
    public static final String TypeURI = "http://www.opengis.net/ont/sf#wktLiteral";

    public static final String CRS84 = "<http://www.opengis.net/def/crs/OGC/1.3/CRS84>";

    public static final RDFDatatype wktLiteralType = new WktLiteral();

    private WktLiteral() {
        super(WktLiteral.TypeURI);
    }

    /**
     * Convert a value of this datatype out
     * to lexical form.
     */
    public String unparse(Object value) {
        return value.toString();
    }

    /**
     * Parse a lexical form of this datatype to a value
     */
    public Object parse(String lexicalForm) {
        return new TypedValue(String.format("%s %s", WktLiteral.CRS84, lexicalForm), this.getURI());
    }

    /**
     * Compares two instances of values of the given datatype.
     * This does not allow rationals to be compared to other number
     * formats, Lang tag is not significant.
     *
     * @param value1 First value to compare
     * @param value2 Second value to compare
     * @return Value to determine whether both are equal.
     */
    public boolean isEqual(LiteralLabel value1, LiteralLabel value2) {
        return value1.getDatatype() == value2.getDatatype()
                && value1.getValue().equals(value2.getValue());
    }

Where it was quite important to return a TypedLiteral in the parse() method. After which I had to do the following to add something to my RDF model:

TypeMapper.getInstance().registerDatatype(WktLiteral.wktLiteralType);
item.addLiteral(GeoSPARQL.asWKT, ResourceFactory.createTypedLiteral(geom, WktLiteral.wktLiteralType));

Where GeoSPARQL.asWKT is the predicate in the GeoSPARQL vocabulary that I generated through schemagen. geom is the geometry object as well known text and WktLiteral.wktLiteralType is an instance of the above class.

In conclusion the result was the following (notation 3):

_:b0 <http://www.w3.org/2003/01/geo/wgs84_pos#lat_long> "POINT (51.61821756986111 5.542408362751153)" .

thus exactly what I wanted... Thanks for all the input.

OTHER TIPS

The syntax is

"POINT (52.83525867111958 6.870789811954563)"^^<http://www.opengis.net/ont/sf#wktLiteral>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top