/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.jena.sparql.resultset; import java.util.ArrayList; import org.apache.jena.atlas.logging.Log; import org.apache.jena.query.ResultSet; import org.apache.jena.rdf.model.*; import org.apache.jena.shared.JenaException; import org.apache.jena.shared.PropertyNotFoundException; import org.apache.jena.sparql.core.Var; import org.apache.jena.sparql.engine.binding.Binding; import org.apache.jena.sparql.engine.binding.BindingFactory; import org.apache.jena.sparql.engine.binding.BindingMap; import org.apache.jena.sparql.vocabulary.ResultSetGraphVocab; import org.apache.jena.vocabulary.RDF; public class RDFInput extends ResultSetMem { /** * Process a result set encoded in RDF according to * <code>@link{http://www.w3.org/2001/sw/DataAccess/tests/result-set}#</code> * * @param model */ public RDFInput(Model model) { buildFromDumpFormat(model); } // Convert from RDF model to in-memory result set private void buildFromDumpFormat(Model resultsModel) { varNames = new ArrayList<>(); StmtIterator sIter = resultsModel.listStatements(null, RDF.type, ResultSetGraphVocab.ResultSet); for ( ; sIter.hasNext() ; ) { // For each root Statement s = sIter.nextStatement(); Resource root = s.getSubject(); buildOneResource(root); } sIter.close(); reset(); } private void buildOneResource(Resource root) { buildVariables(root); int count = buildPreprocess(root); if ( root.getModel().contains(null, ResultSetGraphVocab.index, (RDFNode)null) ) buildRowsOrdered(root, count); else buildRows(root); } private void buildVariables(Resource root) { // Variables StmtIterator rVarsIter = root.listProperties(ResultSetGraphVocab.resultVariable); for ( ; rVarsIter.hasNext() ; ) { String varName = rVarsIter.nextStatement().getString(); varNames.add(varName); } rVarsIter.close(); } private int buildPreprocess(Resource root) { StmtIterator solnIter = root.listProperties(ResultSetGraphVocab.solution); int rows = 0; int indexed = 0; for ( ; solnIter.hasNext() ; ) { Resource soln = solnIter.nextStatement().getResource(); rows++; if ( soln.hasProperty(ResultSetGraphVocab.index) ) indexed++; } solnIter.close(); if ( indexed > 0 && rows != indexed ) { Log.warn(this, "Rows = " + rows + " but only " + indexed + " indexes"); return rows; } return rows; } private void buildRowsOrdered(Resource root, int count) { Model m = root.getModel(); // Assume one result set per file. for ( int index = 1 ;; index++ ) { Literal ind = m.createTypedLiteral(index); StmtIterator sIter = m.listStatements(null, ResultSetGraphVocab.index, ind); if ( !sIter.hasNext() ) break; Statement s = sIter.nextStatement(); if ( sIter.hasNext() ) Log.warn(this, "More than one solution: index = " + index); Resource soln = s.getSubject(); Binding rb = buildBinding(soln); rows.add(rb); sIter.close(); } if ( rows.size() != count ) Log.warn(this, "Found " + rows.size() + ": expected " + count); } private void buildRows(Resource root) { // Now the results themselves int count = 0; StmtIterator solnIter = root.listProperties(ResultSetGraphVocab.solution); for ( ; solnIter.hasNext() ; ) { Resource soln = solnIter.nextStatement().getResource(); count++; Binding rb = buildBinding(soln); rows.add(rb); } solnIter.close(); if ( root.hasProperty(ResultSetGraphVocab.size) ) { try { int size = root.getRequiredProperty(ResultSetGraphVocab.size).getInt(); if ( size != count ) Log.warn(this, "Warning: Declared size = " + size + " : Count = " + count); } catch (JenaException rdfEx) {} } } private Binding buildBinding(Resource soln) { // foreach row BindingMap rb = BindingFactory.create(); StmtIterator bindingIter = soln.listProperties(ResultSetGraphVocab.binding); for ( ; bindingIter.hasNext() ; ) { Resource binding = bindingIter.nextStatement().getResource(); String var = binding.getRequiredProperty(ResultSetGraphVocab.variable).getString(); try { RDFNode val = binding.getRequiredProperty(ResultSetGraphVocab.value).getObject(); rb.add(Var.alloc(var), val.asNode()); } catch (PropertyNotFoundException ex) { Log.warn(this, "Failed to get value for ?" + var); } // We include the value even if it is the marker term "rs:undefined" // if ( val.equals(ResultSetVocab.undefined)) // continue ; // The ResultSetFormatter code equates null (not found) with // rs:undefined. When Jena JUnit testing, it does not matter if the // recorded result has the term absent or explicitly undefined. } bindingIter.close(); return rb; } /** * Turns an RDF model, with properties and classses from the result set * vocabulary, into a SPARQL result set. The result set formed is a copy in * memory. * * @param model * @return ResultSet */ public static ResultSet fromRDF(Model model) { return new RDFInput(model); } }