Как создать ввод списка SPARQL с помощью jena querybuilder?

У меня есть куча кода, который использует API-интерфейс построения запросов Apache Jena (класс SelectBuilder). Я пытаюсь добавить такой термин в свой существующий запрос SPARQL:

        (?a ?b ?c) :hasMagicProperty ?this .

Я убедился, что этот запрос работает в TopBraid, но не могу понять, как представить (?a, ?b, ?c) в Jena API. Что мне нужно сделать, чтобы преобразовать этот список Vars в действительный ресурсный узел Jena?

Я готов изучить альтернативные фреймворки для построения SPARQL, если они имеют надежную поддержку типизированных литералов, IRI и фильтров, а также эту конструкцию списка. Я просмотрел несколько других фреймворков для создания запросов SPARQL, но ни в одной из них нет конструкции списка.

Изменить

Мой код построения запроса (в Groovy) выглядит примерно так:

def selectBuilder = new SelectBuilder()
selectBuilder.addPrefixes(...)
def thisVar = Var.alloc('this')
selectBuilder.addOptional(thisVar, 'rdf:type', ':MyEntity')

def aVar = Var.alloc('a')
def bVar = Var.alloc('b')
def cVar = Var.alloc('c')
List<Var> abc = [aVar, bVar, cVar]
//this doesn't work!!!
selectBuilder.addWhere(abc, ':hasMagicProperty', thisVar)
selectBuilder.addWhere(aVar, ':hasACode', 'code A')
selectBuilder.addWhere(bVar, ':hasBCode', 'code B')
selectBuilder.addWhere(cVar, ':hasCCode', 'code C')

def sparqlQuery = selectBuilder.buildString()

Я потратил пару часов, пытаясь работать с классом RDFList, и я так и не понял. Я продолжу попытки и посмотрю, смогу ли я это понять. В то же время, любая помощь будет оценена по достоинству. :)

Изменить

Вот неудачная попытка использовать RDFList:

//this code does not work!
def varNode = NodeFactory.createVariable('a')
def model = ModelFactory.createDefaultModel()
def rdfNode = model.asRDFNode(varNode)

def rdfList = new RDFListImpl(model.createResource().asNode(), model)
//this line throws an exception!!
rdfList.add(rdfNode)
selectBuilder.addWhere(rdfList, ':hasMagicProperty', thisVar)

//com.hp.hpl.jena.shared.PropertyNotFoundException: http://www.w3.org/1999/02/22-rdf-syntax-ns#rest

person RMorrisey    schedule 26.10.2015    source источник
comment
Я считаю, что вам нужно использовать RDFList. jena.apache.org/documentation/ javadoc/jena/org/apache/jena/rdf/   -  person doog abides    schedule 26.10.2015
comment
@doogabides Спасибо за ответ. Я потратил некоторое время на изучение RDFList API, но не смог понять, как создать его с помощью jena Vars. Не могли бы вы предоставить образец кода?   -  person RMorrisey    schedule 27.10.2015


Ответы (2)


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

/*
 * Jena querybuilder does not yet support RDF lists. See:
 * http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#collections
 */
private Node buildRdfCollection(SelectBuilder queryBuilder, List<?> itemList) {
    if (itemList.isEmpty()) {
        return RDF.nil.asNode()
    }

    def head = itemList.first()
    def rest = buildRdfCollection(queryBuilder, itemList.subList(1, itemList.size()))

    def listNode = NodeFactory.createAnon()
    queryBuilder.addWhere(listNode, RDF.first, head)
    queryBuilder.addWhere(listNode, RDF.rest, rest)
    return listNode
}

...

def listNode = buildRdfCollection(queryBuilder, abc)
queryBuilder.addWhere(listNode, ':hasMagicProperty', thisVar)

Сгенерированный код SPARQL выглядит следующим образом:

_:b0      rdf:first             ?c ;
          rdf:rest              rdf:nil .
_:b1      rdf:first             ?b ;
          rdf:rest              _:b0 .
_:b2      rdf:first             ?a ;
          rdf:rest              _:b1 ;
          :hasMagicProperty  ?this .

Это длинный эквивалент:

(?a ?b ?c) :hasMagicProperty ?this .
person RMorrisey    schedule 28.10.2015

Я написал queryBuilder и не думаю, что в текущем состоянии он будет делать то, что вы хотите. Построитель запросов основан на (но еще не полностью) рекомендации w3c SPARQL 1.1: http://www.w3.org/TR/2013/REC-sparql11-query-20130321/#rQuery

Однако я думаю, что вы можете создать свой запрос, используя Jena QueryFactory.

String queryString = "SELECT * WHERE {  "+
  " OPTIONAL { ?this a :MyEntity } ."+
  " (?a ?b ?c) :hasMagicProperty ?result . "+
  " ?a :hasACode 'code A' . "+
  " ?b :hasACode 'code B' . "+
  " ?c :hasACode 'code C' ."+
  " }";
Query query = QueryFactory.create(queryString) ;

К сожалению, я не думаю, что это то, чего вы действительно хотите. Обратите внимание, что «это» не связано ни с одним из других утверждений, поэтому будет получено перекрестное произведение всех субъектов типа :MyEntity с привязками ?a, ?b, ?c и «результат».

Если вы можете создать запрос с помощью QueryFactory, я могу гарантировать, что QueryBuilder его поддержит.

ОБНОВЛЕНИЕ Я обновил QueryBuilder (следующий снимок должен содержать изменения). Теперь вы должны быть в состоянии сделать следующее:

Var aVar = Var.alloc('a')
Var bVar = Var.alloc('b')
Var cVar = Var.alloc('c')
selectBuilder.addWhere(selectBuilder.list(aVar, bVar, cVar),  ':hasMagicProperty', thisVar)
selectBuilder.addWhere(aVar, ':hasACode', 'code A')
selectBuilder.addWhere(bVar, ':hasBCode', 'code B')
selectBuilder.addWhere(cVar, ':hasCCode', 'code C')

Если вы также можете просто добавить стандартные текстовые версии значений в параметры списка, например:

selectBuilder.list( "<a>", "?b", "'c'" )
person cWarren    schedule 27.10.2015
comment
Спасибо! Это было бы круто! Я предоставлю вам более полный пример запроса. Вот соответствующий раздел спецификации SPARQL 1.1: w3. org/TR/2013/REC-sparql11-query-20130321/#collections - person RMorrisey; 28.10.2015
comment
Изменил "?result" в первом примере фрагмента запроса на "?this", так что то, что я пытаюсь сделать, имеет больше смысла. - person RMorrisey; 28.10.2015