Exactly, I was suggestion only to allocate LinkedHashSets instead of HashSets. I tried this solution on my code version, using LinkedHashSets in this classes:

 * org.apache.clerezza.rdf.core.sparql.query.impl.SimpleBasicGraphPattern
 * org.apache.clerezza.rdf.core.sparql.query.impl.SimpleConstructQuery
 * org.apache.clerezza.rdf.core.sparql.query.impl.SimpleDataSet
 * org.apache.clerezza.rdf.core.sparql.query.impl.SimpleGroupGraphPattern

And the test case that I suggested doesn't fail anymore. On the other side, I checked the generated strings and the FILTER and OPTIONAL sentences are not in the original order. This is the original query:

*PREFIX mo: <http://www.tech-it-easy-project.eu/ontologies/market_ontology.owl#>**
**PREFIX list: <http://jena.hpl.hp.com/ARQ/list#>**
**PREFIX owl: <http://www.w3.org/2002/07/owl#>**
**PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>**
**PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>**
**PREFIX dc: <http://purl.org/dc/elements/1.1/>**
**SELECT ?property ?range ?property_description ?subproperty ?subproperty_description**
**WHERE**
**{**
**    ?property a owl:ObjectProperty .**
**    FILTER (?property != owl:bottomObjectProperty) .**
**    {**
**        {**
**            ?property rdfs:domain ?superclass .**
**            mo:Company rdfs:subClassOf ?superclass .**
**        }**
**        UNION**
**        {**
**            ?property rdfs:domain ?dunion .**
**            ?dunion owl:unionOf ?dlist .**
**            ?dlist list:member ?superclass .**
**            mo:Company rdfs:subClassOf ?superclass .**
**        }**
**    }**
**    {**
**        {**
**            ?property rdfs:range ?superrange .**
**            ?range rdfs:subClassOf ?superrange .**
**            FILTER (!isBlank(?range)) .**
**        }**
**        UNION**
**        {**
**            ?property rdfs:range ?range .**
**            FILTER (!isBlank(?range)) .**
**        }**
**    } .**
**    FILTER (?range != owl:Nothing) .**
** OPTIONAL { ?somesub rdfs:subClassOf ?range . FILTER(?somesub != owl:Nothing && ?somesub != ?range)}**
**    FILTER (!bound(?somesub)) .**
**    OPTIONAL**
**    {**
**        ?subproperty rdfs:subPropertyOf ?property .**
** FILTER(?subproperty != owl:bottomObjectProperty && ?subproperty != ?property)** ** OPTIONAL { ?subproperty dc:description ?subproperty_description . }**
**    }**
**    OPTIONAL { ?property dc:description ?property_description . }**
**} *

And this is the serialized string:

*SELECT ?property ?range ?property_description ?subproperty ?subproperty_description **
**WHERE**
**{**
** ?property <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://www.w3.org/2002/07/owl#ObjectProperty> .**
**    {**
**        {**
** ?property <http://www.w3.org/2000/01/rdf-schema#domain> ?superclass .** **<http://www.tech-it-easy-project.eu/ontologies/market_ontology.owl#Company> <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?superclass .**
**        } **
**        UNION**
**        {**
** ?property <http://www.w3.org/2000/01/rdf-schema#domain> ?dunion .**
**            ?dunion <http://www.w3.org/2002/07/owl#unionOf> ?dlist .**
** ?dlist <http://jena.hpl.hp.com/ARQ/list#member> ?superclass .** **<http://www.tech-it-easy-project.eu/ontologies/market_ontology.owl#Company> <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?superclass .**
**        }**
**    }**
**    {**
**        {**
** ?property <http://www.w3.org/2000/01/rdf-schema#range> ?superrange .** ** ?range <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?superrange .**
**            FILTER (! (isBLANK(?range)))**
**        }**
**        UNION**
**        {**
** ?property <http://www.w3.org/2000/01/rdf-schema#range> ?range .**
**            FILTER (! (isBLANK(?range)))**
**        }**
**    }**
**    OPTIONAL**
**    {**
** ?somesub <http://www.w3.org/2000/01/rdf-schema#subClassOf> ?range .** ** FILTER (((?somesub) != (<http://www.w3.org/2002/07/owl#Nothing>)) && ((?somesub) != (?range)))**
**    }**
**    OPTIONAL**
**    {**
** ?subproperty <http://www.w3.org/2000/01/rdf-schema#subPropertyOf> ?property .** ** OPTIONAL { ?subproperty <http://purl.org/dc/elements/1.1/description> ?subproperty_description . }** ** FILTER (((?subproperty) != (<http://www.w3.org/2002/07/owl#bottomObjectProperty>)) && ((?subproperty) != (?property)))**
**    }**
** OPTIONAL { ?property <http://purl.org/dc/elements/1.1/description> ?property_description . }** ** FILTER ((?property) != (<http://www.w3.org/2002/07/owl#bottomObjectProperty>))**
**    FILTER ((?range) != (<http://www.w3.org/2002/07/owl#Nothing>))**
**    FILTER (! (BOUND(?somesub)))**
**} *

I checked this version of the serialized query on the reasoner powered graph that raised the problem and it worked fine.

Il 08/12/2012 17:54, Reto Bachmann-Gmür ha scritto:
Ok, so you're suggesting not to change any interface but simly the
implemenentation to preserve the order, if the order has no relevane by the
sparql spec then I would prefer that solution.

Cheers,
Reto

On Sat, Dec 8, 2012 at 5:42 PM, Giuseppe Miscione <
g.misci...@innovationengineering.eu> wrote:

Hi Reto,
in revision 1353713 SimpleBasicGraphPattern contains this code:

public SimpleBasicGraphPattern(Set<**TriplePattern> triplePatterns) {
     this.triplePatterns = (triplePatterns == null)
     ? new HashSet<TriplePattern>()
     : triplePatterns;
}

This implementation uses an HashSet that will mess up the order of the
added elements. By simply allocating a LinkedHashSet you'll keep the Set
logic (no duplicates) and you'll preserve the order in which the elements
are added to the set. BasicGraphPattern won't be affected at all, it will
continue to espose a Set, but the underlying LinkedHashSet implementation
will keep the order of the triple patterns.
I don't know why Sets were used before (maybe to avoid the presence of a
duplicate triple pattern in the same graph pattern?), but the solution
implemented by Hasan completely changed the interface of BasicGraphPattern
, deprecating a method and adding an equivalent one.

Il 08/12/2012 17:13, Reto Bachmann-Gmür ha scritto:

Hi Giuseppe and Hasan

If the order of the order of patter is relevant then this should model
this
as a list. Using LinkeddHashSet in BasicGraphPattern would tie this to a
particular implementation. As far as I know the order of the clauses has
no
relevance by the sparql spec (like the order of triples in a graph). But
we
could maybe change our implementation so that it no longer supports
querying by queries described as object trees but only as string, the
parsing necessary for the fastlane could be limited to detecting the type
of query (to parse the result in the right way) and the graphs agains
which
the query is directed.

Cheers,
Reto


On Sat, Dec 8, 2012 at 3:45 PM, Giuseppe Miscione <
g.miscione@**innovationengineering.eu<g.misci...@innovationengineering.eu>>
wrote:

  Hi Hasan,
I had a look at the code changes that you've made.
I saw that you introduced in the parser produced objects methods that now
works with Lists and you've deprecated the methods working with Sets.
Now,
I have a personal cosideration: wouldn't it be easier to restore the old
code and use LinkedHashSets instead of HashSets, without changing so much
the class interfaces with the introduction of deprecated methods?

Il 08/12/2012 14:27, Hasan Hasan ha scritto:

   Hi Giuseppe

I have resolved the issue
CLEREZZA-725<https://issues.****apache.org/jira/browse/****CLEREZZA-725<http://apache.org/jira/browse/**CLEREZZA-725>
<https://issues.**apache.org/jira/browse/**CLEREZZA-725<https://issues.apache.org/jira/browse/CLEREZZA-725>
which
reflects the problem you raised.

Kind regards
Hasan

On Tue, Dec 4, 2012 at 11:34 PM, Hasan Hasan <ha...@trialox.org> wrote:

   Thanks Giuseppe

*
*
I'll try the test as soon as I have time during this week.

Cheers
Hasan


On Mon, Dec 3, 2012 at 3:13 PM, Giuseppe Miscione <
g.miscione@**innovationenginee**ring.eu<http://innovationengineering.eu>
<g.miscione@**innovationengineering.eu<g.misci...@innovationengineering.eu>
wrote:

   Hi Hasan,

I prepared a JUnit test method that clarifies the problem:

@Test
public void testParseMultipleTimes() throws Exception {
       String queryString =
           "PREFIX mo: <http://www.tech-it-easy-**
project.eu/ontologies/market_******ontology.owl#<http://project.eu/ontologies/market_****ontology.owl#>
<http://**project.eu/ontologies/market_****ontology.owl#<http://project.eu/ontologies/market_**ontology.owl#>
<http://www.**tech-it-easy-**project.eu/**ontologies/**
market_ontology.**<http://tech-it-easy-project.eu/**ontologies/market_ontology.**>

owl#<http://www.tech-it-easy-**project.eu/ontologies/market_**
ontology.owl#<http://www.tech-it-easy-project.eu/ontologies/market_ontology.owl#>
\n"
+
           "PREFIX list: 
<http://jena.hpl.hp.com/ARQ/******list#<http://jena.hpl.hp.com/ARQ/****list#>
<http://jena.hpl.hp.**com/ARQ/**list#<http://jena.hpl.hp.com/ARQ/**list#>
<http://jena.hpl.hp.com/**ARQ/**list#<http://jena.hpl.hp.com/**ARQ/list#><
http://jena.hpl.hp.com/ARQ/**list# <http://jena.hpl.hp.com/ARQ/list#>
\n"
+
           "PREFIX owl: 
<http://www.w3.org/2002/07/******owl#<http://www.w3.org/2002/07/****owl#>
<http://www.w3.org/2002/**07/**owl#<http://www.w3.org/2002/07/**owl#>
<http://www.w3.org/2002/**07/**owl#<http://www.w3.org/2002/**07/owl#><
http://www.w3.org/2002/07/**owl# <http://www.w3.org/2002/07/owl#>
\n"
+
           "PREFIX rdf: <http://www.w3.org/1999/02/22-**
****rdf-syntax-ns# <http://www.w3.org/1999/02/22-****rdf-syntax-ns#><
http://www.**w3.org/1999/02/22-**rdf-**syntax-ns#<http://www.w3.org/1999/02/22-**rdf-syntax-ns#>
<http://www.**w3.org/1999/02/**22-rdf-syntax-**ns#<http://w3.org/1999/02/22-rdf-syntax-**ns#>
<http://**www.w3.org/1999/02/22-rdf-**syntax-ns#<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
\n"
+
           "PREFIX rdfs: 
<http://www.w3.org/2000/01/******rdf-schema#<http://www.w3.org/2000/01/****rdf-schema#>
<http://www.w3.**org/2000/01/**rdf-schema#<http://www.w3.org/2000/01/**rdf-schema#>
<http://www.w3.org/**2000/01/**rdf-schema#<http://www.w3.org/**2000/01/rdf-schema#>
<http://www.w3.org/**2000/01/rdf-schema#<http://www.w3.org/2000/01/rdf-schema#>
\n"
+
           "PREFIX dc: 
<http://purl.org/dc/elements/******1.1/<http://purl.org/dc/elements/****1.1/>
<http://purl.org/dc/**elements/**1.1/<http://purl.org/dc/elements/**1.1/>
<http://purl.org/dc/****elements/1.1/<http://purl.org/dc/**elements/1.1/><
http://purl.org/dc/elements/**1.1/ <http://purl.org/dc/elements/1.1/>
  \n"
+
           "SELECT ?property ?range ?property_description ?subproperty
?subproperty_description\n" +
           "WHERE {\n" +
           "    ?property a owl:ObjectProperty .\n" +
           "    FILTER (?property != owl:bottomObjectProperty) .\n" +
           "    {\n" +
           "        {\n" +
           "            ?property rdfs:domain ?superclass .\n" +
           "            mo:Company rdfs:subClassOf ?superclass .\n" +
           "        }\n" +
           "        UNION\n" +
           "        {\n" +
           "            ?property rdfs:domain ?dunion .\n" +
           "            ?dunion owl:unionOf ?dlist .\n" +
           "            ?dlist list:member ?superclass .\n" +
           "            mo:Company rdfs:subClassOf ?superclass .\n" +
           "        }\n" +
           "    }\n" +
           "    {\n" +
           "        {\n" +
           "            ?property rdfs:range ?superrange .\n" +
           "            ?range rdfs:subClassOf ?superrange .\n" +
           "            FILTER (!isBlank(?range)) .\n" +
           "        }\n" +
           "        UNION\n" +
           "        {\n" +
           "            ?property rdfs:range ?range .\n" +
           "            FILTER (!isBlank(?range)) .\n" +
           "        }\n" +
           "    } .\n" +
           "    FILTER (?range != owl:Nothing) .\n" +
           "    OPTIONAL { ?somesub rdfs:subClassOf ?range .
FILTER(?somesub
!= owl:Nothing && ?somesub != ?range)}\n" +
           "    FILTER (!bound(?somesub)) .\n" +
           "    OPTIONAL {\n" +
           "        ?subproperty rdfs:subPropertyOf ?property .\n" +
           "        FILTER(?subproperty != owl:bottomObjectProperty &&
?subproperty != ?property)\n" +
           "        OPTIONAL { ?subproperty dc:description
?subproperty_description . }\n" +
           "    }\n" +
           "    OPTIONAL { ?property dc:description
?property_description
.
}\n" +
           "} ";

       Query query1 = QueryParser.getInstance().******
parse(queryString);
       System.out.println(query1.******toString());

       System.out.println("----------******-------------");

       Thread.sleep(5000l);

       Query query2 = QueryParser.getInstance().******
parse(queryString);
       System.out.println(query2.******toString());

       Assert.assertEquals(query1.******toString(),
query2.toString());

}

By separating the two parse() calls with a 5 seconds sleep, you'll see
that the two parsed objects will produce different strings. Without
the
Thread.sleep() call the test method doesn't fail, so I think there's
something time-related in the javacc parser that will mix up the
parsed
statements.

Regards,
Giuseppe

Il 03/12/2012 10:25, Giuseppe Miscione ha scritto:

    Hi Hasan,

  this is the query on which I was working:
PREFIX mo: <http://www.tech-it-easy-****pro**
ject.eu/ontologies/market_** <http://project.eu/ontologies/**
market_** <http://project.eu/ontologies/market_**>>
ontology.owl#<http://www.tech-****it-easy-project.eu/**ontologies/**<http://it-easy-project.eu/ontologies/**>
market_ontology.owl#<http://**www.tech-it-easy-project.eu/**
ontologies/market_ontology.**owl#<http://www.tech-it-easy-project.eu/ontologies/market_ontology.owl#>
PREFIX list: 
<http://jena.hpl.hp.com/ARQ/******list#<http://jena.hpl.hp.com/ARQ/****list#>
<http://jena.hpl.hp.**com/ARQ/**list#<http://jena.hpl.hp.com/ARQ/**list#>
<http://jena.hpl.hp.com/**ARQ/**list#<http://jena.hpl.hp.com/**ARQ/list#><
http://jena.hpl.hp.com/ARQ/**list#<http://jena.hpl.hp.com/ARQ/list#>
PREFIX owl: 
<http://www.w3.org/2002/07/******owl#<http://www.w3.org/2002/07/****owl#>
<http://www.w3.org/2002/**07/**owl#<http://www.w3.org/2002/07/**owl#>
<http://www.w3.org/2002/**07/**owl#<http://www.w3.org/2002/**07/owl#><
http://www.w3.org/2002/07/**owl# <http://www.w3.org/2002/07/owl#>>>
PREFIX rdf: 
<http://www.w3.org/1999/02/22-******rdf-syntax-ns#<http://www.w3.org/1999/02/22-****rdf-syntax-ns#>
<http://www.**w3.org/1999/02/22-**rdf-**syntax-ns#<http://www.w3.org/1999/02/22-**rdf-syntax-ns#>
<http://www.**w3.org/1999/02/**22-rdf-syntax-**ns#<http://w3.org/1999/02/22-rdf-syntax-**ns#>
<http://**www.w3.org/1999/02/22-rdf-**syntax-ns#<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs: 
<http://www.w3.org/2000/01/******rdf-schema#<http://www.w3.org/2000/01/****rdf-schema#>
<http://www.w3.**org/2000/01/**rdf-schema#<http://www.w3.org/2000/01/**rdf-schema#>
<http://www.w3.org/**2000/01/**rdf-schema#<http://www.w3.org/**2000/01/rdf-schema#>
<http://www.w3.org/**2000/01/rdf-schema#<http://www.w3.org/2000/01/rdf-schema#>
PREFIX dc: 
<http://purl.org/dc/elements/******1.1/<http://purl.org/dc/elements/****1.1/>
<http://purl.org/dc/**elements/**1.1/<http://purl.org/dc/elements/**1.1/>
<http://purl.org/dc/****elements/1.1/<http://purl.org/dc/**elements/1.1/><
http://purl.org/dc/elements/**1.1/<http://purl.org/dc/elements/1.1/>
SELECT ?property ?range ?property_description ?subproperty
?subproperty_description
WHERE {
       ?property a owl:ObjectProperty .
       FILTER (?property != owl:bottomObjectProperty) .
       {
           {
               ?property rdfs:domain ?superclass .
               mo:Company rdfs:subClassOf ?superclass .
           }
           UNION
           {
               ?property rdfs:domain ?dunion .
               ?dunion owl:unionOf ?dlist .
               ?dlist list:member ?superclass .
               mo:Company rdfs:subClassOf ?superclass .
           }
       }
       {
           {
               ?property rdfs:range ?superrange .
               ?range rdfs:subClassOf ?superrange .
               FILTER (!isBlank(?range)) .
           }
           UNION
           {
               ?property rdfs:range ?range .
               FILTER (!isBlank(?range)) .
           }
       } .
       FILTER (?range != owl:Nothing) .
       OPTIONAL { ?somesub rdfs:subClassOf ?range . FILTER(?somesub !=
owl:Nothing && ?somesub != ?range)}
       FILTER (!bound(?somesub)) .
       OPTIONAL {
           ?subproperty rdfs:subPropertyOf ?property .
           FILTER(?subproperty != owl:bottomObjectProperty &&
?subproperty
!= ?property)
           OPTIONAL { ?subproperty dc:description
?subproperty_description
. }
       }
       OPTIONAL { ?property dc:description ?property_description . }
}

Il 03/12/2012 07:53, Hasan Hasan ha scritto:

   Hi Giuseppe

can you please provide an example of the query that you use and
that I
can
reproduce easily?
I will try to take some time this week to have a look.

Kind regards
Hasan

On Fri, Nov 30, 2012 at 5:36 PM, Giuseppe Miscione <
g.miscione@****innovationenginee**ring.eu<htt**
p://innovationengineering.eu <http://innovationengineering.eu>>

<g.miscione@**innovationengine**ering.eu<http://innovationengineering.eu>
<g.miscione@**innovationengineering.eu<g.misci...@innovationengineering.eu>
wrote:

    Hi all,

  I found a bug in the SPARQL query execution chain, specifically in
the
*org.apache.clerezza.rdf.core.********sparql.query.Query* objects

serialization
made with the *org.apache.clerezza.rdf.core.****
****sparql.query.impl.****
SimpleStringQuerySerializer*
methods.
The problem comes from the fact that the javacc objects used for
mapping
triple patterns are not listed in the same order as in the original
query
string. *SimpleStringQuerySerializer* serializes patterns into the
ouput
string in the order returned by the javacc parser, and so the
output
string
won't always be equivalent to the source one. Moreover, parsing
multiple
times the same query string will result in different output
strings.

This problem is even more annoying when executing (like in my case)
queries on graphs enanched with Pellet reasoner, because it has
obviuos
difficulties in inferencing relations if the order of triple
patterns
in
the query is not the provided one.

I solved the problem in my environment by simply saving the
original
string into the parsed *Query *object and then making
*SimpleStringQuerySerializer* returns this string, without any
processing.

Can anyone take a look at the serializer to find a maybe better
solution
to avoid this weird behaviour?

Regards,
Giuseppe Miscione






Reply via email to