несуществующий '.' вызывает ошибку синтаксического анализа после добавления троек Jena ElementGroup

Я пытаюсь создать новый запрос на основе заданного запроса (старый запрос — я не могу его изменить).

Предположим, мне дан простой действительный запрос SPARQL, SELECT ?s WHERE{ ?s ?p ?o }. Допустим, я создаю объект запроса jena из вышеуказанного запроса и получаю шаблон запроса в виде ElementGroup в java следующим образом:

Query q = QueryFactory.create("SELECT ?s WHERE{ ?s ?p ?o }, Syntax.syntaxSPARQL_11);
ElementGroup oldQP = (ElementGroup)q.getQueryPattern();

Раньше я добавлял новые триплеты к старому шаблону запроса, используя следующий синтаксис:

Triple t = Triple.create(...);
oldQP.addTriplePattern(t);

Однако, когда вы переходите к созданию нового объекта запроса:

Query nq = q.cloneQuery();
nq.setQueryPattern(oldQP);
nq.setQuerySelectType();
nq.setQueryResultStar(false);
nq.addResultVar("s");

В итоге вы получите запрос, который выглядит как

SELECT ?s WHERE{
    ?s ?p ?o
    ?s2 ?p2 ?s.
}

потому что он не распознает/не заботится о том, чтобы первая тройка не заканчивалась точкой, когда вы устанавливаете QueryPattern объекта. Это приводит к ошибке синтаксического анализа при выполнении запроса...

Encountered " <VAR1> "?s2 "" at line 10, column 3.
Was expecting one of:
"graph" ...
"optional" ...
"minus" ...
"bind" ...
"service" ...
"let" ...
"exists" ...
"not" ...
"filter" ...
"{" ...
"}" ...
";" ...
"," ...
"." ...

потому что это явно недопустимый SPARQL. Итак, как избежать этой проблемы? Эта проблема не возникает, если у всех троек есть периоды закрытия, но я не могу найти способ заставить это работать.

Спасибо!


person Nick Bartlett    schedule 22.03.2013    source источник


Ответы (3)


Следующий код создает запрос, как вы описали, копирует его, добавляет тройной шаблон, печатает его и выполняет оба запроса. Вы правы, что в печатной форме запроса отсутствует . там, где он обычно присутствует. Однако, как указал RobV, странность печати никак не влияет на результаты запроса. Если вы получаете разные результаты в вашем реальном случае, можете ли вы выделить, где они отличаются от этого?

import com.hp.hpl.jena.graph.Triple;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.ResultSetFormatter;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.sparql.core.Var;
import com.hp.hpl.jena.sparql.syntax.ElementGroup;

public class AddTriplePattern {
    public static void main(String[] args) {
        // Create the original query
        final String queryString = "" +
                "select * where {\n" +
                "  ?s ?p ?o .\n" +
                "}\n" +
                "";
        final Query query = QueryFactory.create( queryString );

        // Create the new query and add `?s2 ?p2 ?o2`. Print the new query
        // before and after adding the triple pattern.  Sure enough, after 
        // the modification, the pattern is printed without a `.` between the 
        // triples.  The space between the variables is also a bit bigger.
        final Query newQuery = QueryFactory.create( query );
        System.out.println( "== before ==\n"+newQuery );
        final ElementGroup eg = (ElementGroup) newQuery.getQueryPattern();
        final Triple t = new Triple( Var.alloc( "s2"), Var.alloc( "p2" ), Var.alloc( "o2" ));
        eg.addTriplePattern( t );
        newQuery.setQueryResultStar(false);
        newQuery.addResultVar( "s2" );
        System.out.println( "== after ==\n"+newQuery );

        // Create a model with a single triple [a, a, a].
        final Model model = ModelFactory.createDefaultModel();
        final Resource a = model.createResource( "urn:ex:a" );
        model.add( a, a.as( Property.class ), a );

        // Run both the original query and the new query on the model.  Both
        // return the expected results.
        ResultSetFormatter.out( QueryExecutionFactory.create( query, model ).execSelect() );
        ResultSetFormatter.out( QueryExecutionFactory.create( newQuery, model ).execSelect() );
    }
}

Результат:

== before ==
SELECT  *
WHERE
  { ?s ?p ?o }

== after ==
SELECT  ?s2
WHERE
  { ?s ?p ?o
    ?s2  ?p2  ?o2 .
  }

----------------------------------------
| s          | p          | o          |
========================================
| <urn:ex:a> | <urn:ex:a> | <urn:ex:a> |
----------------------------------------
--------------
| s2         |
==============
| <urn:ex:a> |
--------------
person Joshua Taylor    schedule 24.07.2013
comment
Re: отсутствует. Старая ошибка - исправлена ​​(по крайней мере, в кодовой базе разработки). - person AndyS; 25.07.2013
comment
Ответ @AndyS RobV предполагает, что он тоже известен и стар. Я просто хотел получить здесь полный рабочий пример для всех, кто придет; теперь они могут видеть, что они должны уметь делать. - person Joshua Taylor; 25.07.2013

Я не уверен, что полностью следую вашему вопросу здесь

Откуда берется второй запрос? Вы вызываете toString() для нового объекта запроса, и в этом случае это может быть ошибка во внутренней логике для печати запросов.

И какую версию ARQ вы используете?

person RobV    schedule 22.03.2013
comment
System.out.println(nq.serialize()); --так что да, печать нового объекта запроса. Но выполнение некоторой отладки приводит к тому, что сама ElementGroup (здесь oldQP), похоже, выглядит так, поэтому я не верю, что это конкретно печать. Извините за путаницу. По сути, проблема заключается в том, что когда вы добавляете триплеты в queryPattern, который выглядит как {?s ?p ?o}, вы получаете шаблон запроса, который выглядит как {?s ?p ?o ?s2 ?p2 ?s. ?s3 ?p3 ?s2.} и т. д., с.т. первая тройка и следующая добавленная тройка не разделены правильным синтаксисом (символ '.'). Думаю, я использую arq-2.8.5-patched-2.jar. - person Nick Bartlett; 22.03.2013
comment
Хорошо, ваша проблема, скорее всего, в том, что это действительно старая версия ARQ, 2.8.5 от июля 2010 года, текущая версия 2.10.0 была выпущена в марте 2013 года. Если вы можете, вам следует действительно обновить ваша зависимость. - person RobV; 23.03.2013
comment
Снова читая ваш вопрос, почему вы распечатываете его как строку и снова анализируете? Разве нельзя просто выполнить новый объект запроса, который вы создали напрямую, тем самым полностью избегая этой проблемы? - person RobV; 23.03.2013
comment
Извини. Я не распечатываю строку и не анализирую ее снова. Я просто выполняю новый объект запроса, который я создал напрямую; распечатанный запрос, который я дал выше, предназначен только для того, чтобы обобщить/обрисовать проблему. По сути, когда у вас есть QueryPattern (Element), который выглядит так: {?s ?p ?o} (полученный, например, с помощью метода Query.getQueryPattern()), и вы пытаетесь добавить к нему триплеты с помощью метода ElementGroup.addTriplePattern(...), вы получаете ElementGroup, который выглядит как {?s ?p ?p ?s2 ?p2 ?s...}, обратите внимание несуществующий период. Это вызывает проблемы при создании нового объекта запроса. - person Nick Bartlett; 25.03.2013
comment
Точка - это просто синтаксис сериализации и не имеет внутреннего представления в коде, если это вызывает проблему, что-то в вашем коде должно в какой-то момент превращать запрос в строку. Независимо от моего предположения, это ошибка в версии ARQ, которой вы пользуетесь почти 3 года назад, чтобы повторить, пожалуйста, обновитесь до более новой версии и посмотрите, сможете ли вы воспроизвести проблему. - person RobV; 25.03.2013

Итак, я, кажется, нашел обходной путь/решение. После отладки и более внимательного изучения объекта ElementGroup, созданного строкой

ElementGroup oldQP = (ElementGroup)q.getQueryPattern();

Я заметил, что он содержит объекты ArrayList of Element (полученные с помощью метода ElementGroup.getElements()). Единственное, что было в этом списке до того, как я попытался добавить триплеты (методом ElementGroup.addTriplePattern(...)), был объект типа ElementPathBlock. Хорошо.

Затем я пытаюсь добавить триплеты с помощью описанного выше метода, например так:

Triple t = Triple.create(...);
oldQP.addTriplePattern(t);

Я заметил, что это добавляет новый ElementTriplesBlock в список элементов ElementGroup. Кажется, это и есть виновник. Итак, мое решение состояло в том, чтобы вместо этого взять последнее вхождение ElementPathBlock и добавить триплеты к этому объекту вместо добавления их в ElementGroup (таким образом избегая добавления нового ElementTriplesBlock в ArrayList):

//same as before
Query q = QueryFactory.create("SELECT ?s WHERE{ ?s ?p ?o }, Syntax.syntaxSPARQL_11);
Query nq = q.cloneQuery();
ElementGroup oldQP = (ElementGroup)q.getQueryPattern();
Triple t = Triple.create(Var.alloc("s2"), Var.alloc("p2"), Var.alloc("s));

//new
ElementPathBlock epb;
int index = -1;
for(int i=0; i<oldQP.getElements().size(); i++){
    if(oldQP.getElements().get(i) instanceof ElementPathBlock){
        //...get last index of instanceof ElementPathBlock, if exists.
        index = i;
    }
}
if(index > -1){
    //...found occurence of ElementPathBlock we will add to
    epb = (ElementPathBlock) oldQP.getElements().get(index);
}else{
    //...no occurence, so make new ElementPathBlock to add
    epb = new ElementPathBlock();
}
//add Triple(s) to epb, not to oldQP
epb.addTriple(t);
//re-add (or add for first time) ElementPathBlock to the ArrayList of Elements
if(index > -1){
    oldQP.getElements().set(index, epb);
}else{
    oldQP.getElements().add(epb);
}

//same as before
nq.setQueryPattern(oldQP);
nq.setQuerySelectType();
nq.setQueryResultStar(false);
nq.addResultVar("s");

Глядя на старый QP теперь, после вышесказанного, мы видим, что он правильно отформатирован, и что точка поставлена ​​правильно:

{?s ?p ?o.
 ?s2 ?p2 ?s.
}
person Nick Bartlett    schedule 25.03.2013