Java 不存在的“.”在添加三元组Jena ElementGroup后导致分析错误

Java 不存在的“.”在添加三元组Jena ElementGroup后导致分析错误,java,sparql,jena,Java,Sparql,Jena,我正在尝试基于给定查询构造新查询-旧查询-我无法更改此设置 假设给我一个简单有效的SPARQL查询,选择?s WHERE{s?p?o}。假设我为上述查询创建了一个jena查询对象,并将查询模式作为java中的ElementGroup获取,如下所示: Query q = QueryFactory.create("SELECT ?s WHERE{ ?s ?p ?o }, Syntax.syntaxSPARQL_11); ElementGroup oldQP = (ElementGroup)q.get

我正在尝试基于给定查询构造新查询-旧查询-我无法更改此设置

假设给我一个简单有效的SPARQL查询,选择?s WHERE{s?p?o}。假设我为上述查询创建了一个jena查询对象,并将查询模式作为java中的ElementGroup获取,如下所示:

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。那么,如何避免这个问题呢?如果所有三元组都有结束期,则不会出现此问题,但我似乎找不到任何方法来实现此功能


谢谢

我不确定我是否完全理解你的问题

第二个查询来自哪里?您是否在新查询对象上调用toString,在这种情况下,这可能是打印查询的内部逻辑中的错误


另外,您使用的是什么版本的ARQ?

因此,我似乎找到了一个解决方法。 在调试并更仔细地查看由该行创建的ElementGroup对象之后

ElementGroup oldQP = (ElementGroup)q.getQueryPattern();
我注意到它显示了通过方法ElementGroup.getElements检索的元素对象的ArrayList。在我试图通过ElementGroup.addTriplePattern添加三元组之前,列表中唯一的一件事。。。方法是ElementPathBlock类型的对象。好的,酷

接下来,我尝试通过上述方法添加三元组,如下所示:

Triple t = Triple.create(...);
oldQP.addTriplePattern(t);
我注意到这将向ElementGroup的元素列表添加一个新的ElementTriplesBlock。看来这就是罪魁祸首。因此,我的解决方案是获取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");

下面的代码如您所述创建查询、复制查询、添加三重模式、打印查询并运行这两个查询。您是对的,查询的打印表单缺少。通常会有人在场的地方。然而,作为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> |
--------------

System.out.printlnnq.serialize-是的,打印新的查询对象。但进行一些调试后,ElementGroup本身的oldQP看起来是这样的,所以我不认为它是专门打印的。很抱歉给你带来了困惑。本质上,问题似乎是,当您将三元组添加到一个类似{s?p?o}的查询模式时,您会得到一个类似{s?p?o?s2?p2?s?s3?p3?s2}等的查询模式,即s.t。添加的第一个三元组和下一个三元组之间没有使用正确的语法a.'字符分隔。我相信我正在使用arq-2.8.5-patched-2.jar。好吧,你的问题很可能是它是一个非常旧的arq版本,2.8.5是从2010年7月开始的,当前的2.10.0版本是在2013年3月发布的。如果你有能力,你真的应该升级你的依赖关系。再次阅读你的问题,为什么你要把它打印成字符串,然后重新解析?不可能直接执行您创建的新查询对象,从而完全避免此问题吗?抱歉。我不会打印成字符串并再次解析它。我只是执行我直接创建的新查询对象;我上面打印出来的查询只是为了总结/概述这个问题。本质上,当您有一个类似以下内容的QueryPattern元素时:{s?p?o}例如通过Query.getQueryPattern方法获得,并且您尝试通过ElementGroup.addTriplePattern向其添加三元组。。。方法,得到一个元素组,看起来像{s?p?p?s2?p2?s…},注意不存在的句点。这会在创建新查询对象时引发问题。句点只是序列化语法,在代码中没有内部表示形式,如果这会导致问题,那么代码中的某些内容一定会在某个时候将查询转换为字符串。不管怎样,我的假设是,这是您正在使用的将近3年的ARQ版本中的一个bug,重申一下,请升级到一个更新的版本,看看您是否仍然可以重现问题re:Missing。旧bug-至少在开发代码库中修复了。@AndyS RobV的回答表明它也是已知的和旧的。我只是想在这里得到一个完整的工作示例,以供其他人参考;现在他们可以看到他们应该能做什么了。
== 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> |
--------------