[ 
https://issues.apache.org/jira/browse/JENA-1841?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17049514#comment-17049514
 ] 

Andy Seaborne edited comment on JENA-1841 at 3/2/20 9:54 PM:
-------------------------------------------------------------

This is enough to trigger the issue: with either "if" block active:
{code:java}
    public static void main(String ... a) {
        UUID uuid = UUID.fromString("00000000-0000-0000-0000-000000000007");

        if ( true ) {
            LiteralLabel ll = LiteralLabelFactory.createTypedLiteral(uuid);
        }

        if ( false ) {
            SelectBuilder select = new SelectBuilder();
            select.getExprFactory().eq("?uuid", uuid);
        }
        // The bad lexical form is not relevant. Just shortened for JIRA.
        String modelStr = "_:a <http://example.org/p1> 
'00000000'^^<java:java.util.UUID> .";
        Model model = ModelFactory.createDefaultModel().read(new 
StringReader(modelStr), "", "N-TRIPLE");
        System.out.println("DONE");
    }
{code}

{{select.getExprFactory().eq("?uuid", uuid);}} calls 
{{LiteralLabelFactory.createTypedLiteral(uuid)}}.
{{LiteralLabelFactory.createTypedLiteral(uuid)}} tries to register a datatype 
for java class UUID - no URI given.

The problem is that there is no full registration for Java Object to datatype 
with URI, only a placeholder ({{AdHocDatatype}}. When the parser runs or any 
way a literal node if created from a string, Jena attempts to find the value 
but there is no code for UUID string to UUID.

What can {{SelectBuilder}} do about unknown datatypes? (Ping [~claude]). It 
does not get the {{<java:java.util.UUID>}}, only the java object, so proper 
registration can't happen. Maybe it should not support unregistered types and 
signal that with a clear exception.

Normally when parsing (RIOT or SPARQL) unknowns, 
{{TypeMapper.getSafeTypeByName}} happens which creates a {{BaseDatatype}} but 
in this case, the datatype URI is known and is the placeholder.

To register a datatype: do this before using {{SelectBuilder}}: (only weakly 
tested):
{code:java}
            RDFDatatype dtx = new BaseDatatype("java:java.util.UUID") {
                @Override
                public Class<?> getJavaClass() {
                    return UUID.class;
                }

                @Override
                public Object parse(String lexicalForm) throws 
DatatypeFormatException {
                    try {
                        return UUID.fromString(lexicalForm);
                    } catch (Throwable th) {
                        throw new DatatypeFormatException();
                    }
                }
            };

            TypeMapper.getInstance().registerDatatype(dtx);
{code}

Finally - did the code mean to use a URI: 
{{<urn:uuid:00000000-0000-0000-0000-000000000007>}}?


was (Author: andy.seaborne):
This is enough to trigger the issue: with either "if" block active:
{code:java}
    public static void main(String ... a) {
        UUID uuid = UUID.fromString("00000000-0000-0000-0000-000000000007");

        if ( true ) {
            LiteralLabel ll = LiteralLabelFactory.createTypedLiteral(uuid);
        }

        if ( false ) {
            SelectBuilder select = new SelectBuilder();
            select.getExprFactory().eq("?uuid", uuid);
        }
        // The bad lexical form is not relevant. Just shortened for JIRA.
        String modelStr = "_:a <http://example.org/p1> 
'00000000'^^<java:java.util.UUID> .";
        Model model = ModelFactory.createDefaultModel().read(new 
StringReader(modelStr), "", "N-TRIPLE");
        System.out.println("DONE");
    }
{code}

{{select.getExprFactory().eq("?uuid", uuid);}} calls 
{{LiteralLabelFactory.createTypedLiteral(uuid)}}.
{{LiteralLabelFactory.createTypedLiteral(uuid)}} tries to register a datatype 
for java class UUID - no URI given.

The problem is that there is no full registration for Java Object to datatype 
with URI, only a placeholder ({{AdHocDatatype}}. When the parser runs or any 
way a literal node if created from a string, Jena attempts to find the value 
but there is no code for UUID string to UUID.

What can {{SelectBuilder}} do about unknown datatypes? (Ping [~claude]). It 
does not get the {{<java:java.util.UUID>}}, only the java object, so proper 
registration can't happen. Maybe it should not support unregistered types and 
signal that with a clear exception.

Normally when parsing (RIOT or SPARQL) unknowns, 
{{TypeMapper.getSafeTypeByName}} happens which creates a {{BaseDatatype}} but 
in this case, the datatype URI is known and is the placeholder.

To register a datatype: do this before using {{SelectBuilder}}: (only weakly 
tested):
{code:java}
            RDFDatatype dtx = new BaseDatatype("java:java.util.UUID") {
                @Override
                public Class<?> getJavaClass() {
                    return UUID.class;
                }

                @Override
                public Object parse(String lexicalForm) throws 
DatatypeFormatException {
                    try {
                        UUID.fromString(lexicalForm);
                        return lexicalForm;
                    } catch (Throwable th) {
                        throw new DatatypeFormatException();
                    }
                }
            };

            TypeMapper.getInstance().registerDatatype(dtx);
{code}

Finally - did the code mean to use a URI: 
{{<urn:uuid:00000000-0000-0000-0000-000000000007>}}?

> Side Effect of Datatype <java:java.util.UUID> Use in Query
> ----------------------------------------------------------
>
>                 Key: JENA-1841
>                 URL: https://issues.apache.org/jira/browse/JENA-1841
>             Project: Apache Jena
>          Issue Type: Bug
>    Affects Versions: Jena 3.14.0
>            Reporter: Jan Martin Keil
>            Priority: Major
>
> I faced a bug caused by a side effect of using the datatype 
> <java:java.util.UUID> in a query.
> Short story is that you can not use this datatype in model parsing or queries 
> after you once used it in a query.
> I did not completely  break it down to a specific peace of code, but I wrote 
> some testcases that narrow down the issue. Please note that the order of 
> execution of the test methods effect the result. So please first try to 
> execute single test methods before executing the whole test class.
> {code:java}
> import java.io.ByteArrayInputStream;
> import java.util.UUID;
> import org.apache.jena.arq.querybuilder.SelectBuilder;
> import org.apache.jena.query.QueryExecution;
> import org.apache.jena.query.QueryExecutionFactory;
> import org.apache.jena.rdf.model.Model;
> import org.apache.jena.rdf.model.ModelFactory;
> import org.junit.jupiter.api.Test;
> public class UuidParsingintoModelOrQuery {
>       @Test
>       public void uuidParsingIntoSingleModel() throws Exception {
>               UUID uuid1 = 
> UUID.fromString("00000000-0000-0000-0000-000000000000");
>               UUID uuid2 = 
> UUID.fromString("00000000-0000-0000-0000-000000000001");
>               String modelStr = "_:a <http://example.org/p1> \"" + uuid1 + 
> "\"^^<java:java.util.UUID> .\n"
>                               + "_:a <http://example.org/p2> \"" + uuid1 + 
> "\"^^<java:java.util.UUID> .";
>               ModelFactory.createDefaultModel().read(new 
> ByteArrayInputStream(modelStr.getBytes()), "", "N-TRIPLE");
>               // repeat
>               modelStr = "_:a <http://example.org/p1> \"" + uuid2 + 
> "\"^^<java:java.util.UUID> .\n"
>                               + "_:a <http://example.org/p2> \"" + uuid2 + 
> "\"^^<java:java.util.UUID> .";
>               ModelFactory.createDefaultModel().read(new 
> ByteArrayInputStream(modelStr.getBytes()), "", "N-TRIPLE");
>       }
>       @Test
>       public void sameUuidParsingIntoSingleModel() throws Exception {
>               UUID uuid1 = 
> UUID.fromString("00000000-0000-0000-0000-000000000002");
>               UUID uuid2 = 
> UUID.fromString("00000000-0000-0000-0000-000000000003");
>               String modelStr = "_:a <http://example.org/p1> \"" + uuid1 + 
> "\"^^<java:java.util.UUID> .\n"
>                               + "_:a <http://example.org/p2> \"" + uuid2 + 
> "\"^^<java:java.util.UUID> .";
>               ModelFactory.createDefaultModel().read(new 
> ByteArrayInputStream(modelStr.getBytes()), "", "N-TRIPLE");
>               // repeat
>               ModelFactory.createDefaultModel().read(new 
> ByteArrayInputStream(modelStr.getBytes()), "", "N-TRIPLE");
>       }
>       @Test
>       public void sameUuidParsingIntoMultipleModel() throws Exception {
>               UUID uuid = 
> UUID.fromString("00000000-0000-0000-0000-000000000004");
>               String modelStr = "_:a <http://example.org/p1> \"" + uuid + 
> "\"^^<java:java.util.UUID> .";
>               ModelFactory.createDefaultModel().read(new 
> ByteArrayInputStream(modelStr.getBytes()), "", "N-TRIPLE");
>               ModelFactory.createDefaultModel().read(new 
> ByteArrayInputStream(modelStr.getBytes()), "", "N-TRIPLE");
>       }
>       @Test
>       public void uuidUseInQuery() throws Exception {
>               UUID uuid = 
> UUID.fromString("00000000-0000-0000-0000-000000000005");
>               SelectBuilder select = new SelectBuilder();
>               select.addWhere("?a", "<http://example.org/p>", "?uuid");
>               select.addFilter(select.getExprFactory().eq("?uuid", uuid));
>               QueryExecution q = QueryExecutionFactory.create(select.build());
>       }
>       @Test
>       public void uuidParsingIntoQuery() throws Exception {
>               UUID uuid = 
> UUID.fromString("00000000-0000-0000-0000-000000000006");
>               SelectBuilder select = new SelectBuilder();
>               select.addWhere("?a", "<http://example.org/p>", "?uuid");
>               select.addFilter(select.getExprFactory().eq("?uuid", uuid));
>               QueryExecution q = 
> QueryExecutionFactory.create(select.toString());
>       }
>       @Test
>       public void uuidUseInQueryAndParsingIntoModel() throws Exception {
>               UUID uuid = 
> UUID.fromString("00000000-0000-0000-0000-000000000007");
>               SelectBuilder select = new SelectBuilder();
>               select.addWhere("?a", "<http://example.org/p>", "?uuid");
>               select.addFilter(select.getExprFactory().eq("?uuid", uuid));
>               QueryExecution q = QueryExecutionFactory.create(select.build());
>               String modelStr = "_:a <http://example.org/p1> \"" + uuid + 
> "\"^^<java:java.util.UUID> .\n"
>                               + "_:a <http://example.org/p2> \"" + uuid + 
> "\"^^<java:java.util.UUID> .";
>               Model model = ModelFactory.createDefaultModel().read(new 
> ByteArrayInputStream(modelStr.getBytes()), "",
>                               "N-TRIPLE");
>       }
> }
> {code}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to