blob: 89e18adb5272c68d81fbbc8ffb2016e3783a954e [file] [log] [blame]
/*
* 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.algebra;
import java.util.Iterator ;
import org.apache.jena.graph.Graph ;
import org.apache.jena.graph.Node ;
import org.apache.jena.query.ARQ ;
import org.apache.jena.query.Dataset ;
import org.apache.jena.query.Query ;
import org.apache.jena.rdf.model.Model ;
import org.apache.jena.shared.PrefixMapping ;
import org.apache.jena.sparql.algebra.optimize.Optimize ;
import org.apache.jena.sparql.core.DatasetGraph ;
import org.apache.jena.sparql.core.DatasetGraphFactory ;
import org.apache.jena.sparql.core.Var ;
import org.apache.jena.sparql.engine.Plan ;
import org.apache.jena.sparql.engine.QueryEngineFactory ;
import org.apache.jena.sparql.engine.QueryEngineRegistry ;
import org.apache.jena.sparql.engine.QueryIterator ;
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.engine.binding.BindingRoot ;
import org.apache.jena.sparql.engine.ref.QueryEngineRef ;
import org.apache.jena.sparql.sse.Item ;
import org.apache.jena.sparql.sse.SSE ;
import org.apache.jena.sparql.sse.builders.BuilderOp ;
import org.apache.jena.sparql.syntax.Element ;
import org.apache.jena.sparql.util.Context ;
/** Utilities to produce SPARQL algebra */
public class Algebra
{
// -------- Optimize
/** Apply static transformations to a query to optimize it */
public static Op optimize(Op op) { return optimize(op, null) ; }
/** Apply static transformations to a query to optimize it */
public static Op optimize(Op op, Context context)
{
if ( context == null )
context = ARQ.getContext() ;
// Call-through to somewhere to manage all the optimizations
if ( op == null )
return null ;
return Optimize.optimize(op, context) ;
}
// -------- Compile
/** Compile a query - pattern and modifiers. */
public static Op compile(Query query)
{
if ( query == null )
return null ;
return new AlgebraGenerator().compile(query) ;
}
/** Compile a pattern.*/
public static Op compile(Element elt)
{
if ( elt == null )
return null ;
return new AlgebraGenerator().compile(elt) ;
}
/** Turn an algebra expression into quadpattern form */
public static Op toQuadForm(Op op)
{
return AlgebraQuad.quadize(op) ;
}
/** Turn an algebra expression into quadblock form */
public static Op toQuadBlockForm(Op op)
{
return AlgebraQuad.quadizeBlock(op) ;
}
/** Transform an algebra expression so that default graph is union of the named graphs.
* Does not work with property paths.
* @deprecated To be removed
*/
@Deprecated
public static Op unionDefaultGraph(Op op)
{
return TransformUnionQuery.transform(op) ;
}
// -------- SSE uses these operations ...
static public Op read(String filename)
{
Item item = SSE.readFile(filename) ;
return parse(item) ;
}
static public Op parse(String string)
{
Item item = SSE.parse(string) ;
return parse(item) ;
}
static public Op parse(String string, PrefixMapping pmap)
{
Item item = SSE.parse(string, pmap) ;
return parse(item) ;
}
static public Op parse(Item item)
{
Op op = BuilderOp.build(item) ;
return op ;
}
// -------- Execute
static public QueryIterator exec(Op op, Dataset ds)
{
return exec(op, ds.asDatasetGraph()) ;
}
static public QueryIterator exec(Op op, Model model)
{
return exec(op, model.getGraph()) ;
}
static public QueryIterator exec(Op op, Graph graph)
{
return exec(op, DatasetGraphFactory.wrap(graph)) ;
}
static public QueryIterator exec(Op op, DatasetGraph ds)
{
QueryEngineFactory f = QueryEngineRegistry.findFactory(op, ds, null) ;
Plan plan = f.create(op, ds, BindingRoot.create(), null) ;
return plan.iterator() ;
}
// Reference engine
static public QueryIterator execRef(Op op, Dataset ds)
{
return execRef(op, ds.asDatasetGraph()) ;
}
static public QueryIterator execRef(Op op, Model model)
{
return execRef(op, model.getGraph()) ;
}
static public QueryIterator execRef(Op op, Graph graph)
{
return execRef(op, DatasetGraphFactory.wrap(graph)) ;
}
static public QueryIterator execRef(Op op, DatasetGraph dsg)
{
QueryEngineRef qe = new QueryEngineRef(op, dsg, ARQ.getContext().copy()) ;
return qe.getPlan().iterator() ;
}
// This is the SPARQL merge rule.
public static Binding merge(Binding bindingLeft, Binding bindingRight)
{
// Test to see if compatible: Iterate over variables in left
boolean matches = compatible(bindingLeft, bindingRight) ;
if ( ! matches )
return null ;
// If compatible, merge. Iterate over variables in right but not in left.
BindingMap b = BindingFactory.create(bindingLeft) ;
for ( Iterator<Var> vIter = bindingRight.vars() ; vIter.hasNext() ; )
{
Var v = vIter.next();
Node n = bindingRight.get(v) ;
if ( ! bindingLeft.contains(v) )
b.add(v, n) ;
}
return b ;
}
public static boolean compatible(Binding bindingLeft, Binding bindingRight)
{
// Test to see if compatible: Iterate over variables in left
for ( Iterator<Var> vIter = bindingLeft.vars() ; vIter.hasNext() ; )
{
Var v = vIter.next();
Node nLeft = bindingLeft.get(v) ;
Node nRight = bindingRight.get(v) ;
if ( nRight != null && ! nRight.equals(nLeft) )
return false ;
}
return true ;
}
public static boolean disjoint(Binding binding1, Binding binding2)
{
Iterator<Var> iterVar1 = binding1.vars() ;
for ( ; iterVar1.hasNext() ; )
{
Var v = iterVar1.next() ;
if ( binding2.contains(v) )
return false ;
}
return true ;
}
}