We are having a problem getting the correct lexical form out of our Jena Adaptor for our user-defined datatype. We have implemented a class to format a represent a currency. This class extends the Jena BaseDatatype and implements parse/unparse and isEqual as suggested by their documentation.
We insert the value of the object into the triple store and the datatype and the value appear to be correct. (603.94, grants-base:dollar) Unfortunately, when we are pulling the data from the triple store, the OracleUtils.createLiteralNode, called by the OracleBatchIterator.createNodeFromQueryResult method, is treating the provided value as a String, rather than a double as I would expect. This means that the lexicalForm of the value is already set, and our implementation of the unparse method is never called.
Is this something that we are doing wrong on insert or on the select? Does the OracleBatchSemIterator treat all values from the resultSet as Strings?
The debug trace looks like:
LiteralLabelImpl.<init>(String, String, RDFDatatype) line: 83
LiteralLabelFactory.createLiteralLabel(String, String, RDFDatatype) line: 16
Node.createLiteral(String, String, RDFDatatype) line: 91
OracleUtils.createLiteralNode(String, String, String, Clob, OracleTranslator) line: 164
OracleBatchSemIterator(OracleSemIterator).createNodeFromQueryResult(String, String, String, Clob, String) line: 713
OracleBatchSemIterator.getObjectsFromResultSet(Set<String>) line: 533
OracleBatchSemIterator.retrieveNodes() line: 273
OracleBatchSemIterator.hasNext() line: 136
OracleLeanQueryIter.hasNextBinding() line: 114
Any guidance would be appreciated.
No. Jena Adapter does not just return strings for typed literals.
If literal type is not null, then we invoke Node.createLiteral(str, null, literalType) to create the literal.
If language is not null, we invoke Node.createLiteral(str, language, null) to create the literal.
Otherwise, it is a plain literal.
For the first case, we rely on Jena's TypeMapper to retrieve the right type given the datatype uri.
I'm not sure that is the behavior that we are seeing. Let me try to detail this a bit further.
We have a custom datatype, ns:dollar. We have implemented a subclass to handle this and added that class to the Jena TypeMapper.
If I execute this sparql:
select o, p, P$RDFLTYP
FROM TABLE (SEM_MATCH(
ns:Application-99001761 ?o ?p
order by 1
I get these values:
ns#extendedCosts 1179.98 ns#dollar
The problem appears to be that the value of the triple is treated as a String rather than an Object. This means that when the createLiteral method is called it passes a string, which it turns passes a string to the LiteralLabelFactory. Looking at the code for LiteralLabelFactory, when a String is provided to the createLiteralLabel method, sets the lexicalForm to that string and never calls the "unparse" method of our extended datatype.
The result is my value out of the database gets treated as the LexicalForm rather than the value, and my call to getLexicalForm always returns 1179.98 rather than the lexicalForm of $1179.98 since the value of lexicalForm is already set when the LiteralLabel is created.