package de.unikiel.inf.comsys.neo4j.inference; /* * #%L * neo4j-sparql-extension * %% * Copyright (C) 2014 Niclas Hoyer * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import de.unikiel.inf.comsys.neo4j.inference.rules.Rule; import de.unikiel.inf.comsys.neo4j.inference.rules.Rules; import de.unikiel.inf.comsys.neo4j.inference.sail.SailTupleExprQuery; import de.unikiel.inf.comsys.neo4j.inference.sail.SailBooleanExprQuery; import de.unikiel.inf.comsys.neo4j.inference.sail.SailGraphExprQuery; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.openrdf.model.ValueFactory; import org.openrdf.query.MalformedQueryException; import org.openrdf.query.Query; import org.openrdf.query.QueryLanguage; import org.openrdf.query.algebra.TupleExpr; import org.openrdf.query.parser.ParsedBooleanQuery; import org.openrdf.query.parser.ParsedGraphQuery; import org.openrdf.query.parser.ParsedQuery; import org.openrdf.query.parser.ParsedTupleQuery; import org.openrdf.query.parser.QueryParser; import org.openrdf.query.parser.QueryParserFactory; import org.openrdf.query.parser.QueryParserRegistry; import org.openrdf.repository.RepositoryException; import org.openrdf.repository.sail.SailRepositoryConnection; /** * A query rewriting implementation that takes a SPARQL query and rewrites * according to a OWL-2 TBox to include inference. * * The query rewriter uses a set of rules to transform SPARQL algebra * expressions. To get a set of rules from an OWL-2 TBox use the {@link Rules} * class. */ public class QueryRewriter { private SailRepositoryConnection conn; private ValueFactory vf; private ArrayList<Rule> rules; /** * Create a new query rewriter. * * @param conn the repository connection used for query execution */ public QueryRewriter(SailRepositoryConnection conn) { this(conn, Collections.EMPTY_LIST); } /** * Create a new query rewriter with a set of rules. * * @param conn the repository connection used for query execution * @param rules the set of rules used for rewriting */ public QueryRewriter( SailRepositoryConnection conn, Rule... rules) { this(conn, Arrays.asList(rules)); } /** * Create a new query rewriter with a set of rules. * * @param conn the repository connection used for query execution * @param rules the set of rules used for rewriting */ public QueryRewriter( SailRepositoryConnection conn, List<Rule> rules) { this.rules = new ArrayList<>(rules); this.conn = conn; this.vf = conn.getValueFactory(); for (Rule r : rules) { r.setValueFactory(vf); } } /** * Rewrite a given query to add inference. * * @param ql the query language used for the query * @param query the query to rewrite * @return rewritten query that includes inference * @throws MalformedQueryException if the query is malformed * @throws RepositoryException if there was a problem while rewriting */ public Query rewrite(QueryLanguage ql, String query) throws MalformedQueryException, RepositoryException { return rewrite(ql, query, null); } /** * Rewrite a given query to add inference. * * @param ql the query language used for the query * @param query the query to rewrite * @param baseuri a base URI to use for the query * @return rewritten query that includes inference * @throws MalformedQueryException if the query is malformed * @throws RepositoryException if there was a problem while rewriting */ public Query rewrite(QueryLanguage ql, String query, String baseuri) throws MalformedQueryException, RepositoryException { // parse query using Sesame QueryParserFactory f = QueryParserRegistry.getInstance().get(ql); QueryParser parser = f.getParser(); ParsedQuery parsed = parser.parseQuery(query, baseuri); // get SPARQL algebra expression from parsed query TupleExpr expr = parsed.getTupleExpr(); // rewrite query using visitor pattern RuleTransformationVisitor visitor = new RuleTransformationVisitor(rules); expr.visit(visitor); // return new query based on rewritten algebra expression return getExprQuery(parsed, expr); } /** * Creates a new query based on a tuple expression and original query. The * new query will have the same type null * ({@link org.openrdf.query.TupleQuery}, * {@link org.openrdf.query.GraphQuery} or * {@link org.openrdf.query.BooleanQuery}) as the given original query. * * @param orig the original query * @param expr the expression used for the new query * @return new query based on expression */ protected Query getExprQuery(ParsedQuery orig, TupleExpr expr) { if (orig instanceof ParsedTupleQuery) { return new SailTupleExprQuery( new ParsedTupleQuery(expr), conn); } else if (orig instanceof ParsedGraphQuery) { return new SailGraphExprQuery( new ParsedGraphQuery(expr), conn); } else { return new SailBooleanExprQuery( new ParsedBooleanQuery(expr), conn); } } }