Package com.hp.hpl.jena.tdb.migrate

Source Code of com.hp.hpl.jena.tdb.migrate.TransformDynamicDataset_Imperfect

/*
* 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 com.hp.hpl.jena.tdb.migrate;

import java.util.HashSet ;
import java.util.Set ;

import org.apache.jena.atlas.logging.Log ;

import com.hp.hpl.jena.graph.Node ;
import com.hp.hpl.jena.graph.Triple ;
import com.hp.hpl.jena.query.Query ;
import com.hp.hpl.jena.sparql.ARQException ;
import com.hp.hpl.jena.sparql.algebra.Op ;
import com.hp.hpl.jena.sparql.algebra.Table ;
import com.hp.hpl.jena.sparql.algebra.TableFactory ;
import com.hp.hpl.jena.sparql.algebra.Transform ;
import com.hp.hpl.jena.sparql.algebra.TransformCopy ;
import com.hp.hpl.jena.sparql.algebra.Transformer ;
import com.hp.hpl.jena.sparql.algebra.op.OpAssign ;
import com.hp.hpl.jena.sparql.algebra.op.OpBGP ;
import com.hp.hpl.jena.sparql.algebra.op.OpDatasetNames ;
import com.hp.hpl.jena.sparql.algebra.op.OpDistinct ;
import com.hp.hpl.jena.sparql.algebra.op.OpGraph ;
import com.hp.hpl.jena.sparql.algebra.op.OpJoin ;
import com.hp.hpl.jena.sparql.algebra.op.OpNull ;
import com.hp.hpl.jena.sparql.algebra.op.OpPath ;
import com.hp.hpl.jena.sparql.algebra.op.OpQuadPattern ;
import com.hp.hpl.jena.sparql.algebra.op.OpSequence ;
import com.hp.hpl.jena.sparql.algebra.op.OpTable ;
import com.hp.hpl.jena.sparql.algebra.op.OpUnion ;
import com.hp.hpl.jena.sparql.algebra.table.Table1 ;
import com.hp.hpl.jena.sparql.core.BasicPattern ;
import com.hp.hpl.jena.sparql.core.Quad ;
import com.hp.hpl.jena.sparql.core.Var ;
import com.hp.hpl.jena.sparql.engine.binding.Binding ;
import com.hp.hpl.jena.sparql.engine.binding.BindingFactory ;
import com.hp.hpl.jena.sparql.engine.main.QC ;
import com.hp.hpl.jena.sparql.expr.NodeValue ;
import com.hp.hpl.jena.sparql.util.NodeUtils ;

/**
* Transform to restrict a query to subset of the named graphs in a datasets,
* both in the named graphs visible, and the default graph as a composition of
* graphs in the datasets.
*/

public class TransformDynamicDataset_Imperfect extends TransformCopy
{
    /*
     * ** Problems with paths - that code accesses the active graph.
     * ** See also Dynamic Dataset which forms a general DatasetGraph
     */
   
    // The graphs making up the usual default graph of the query.
    private Set<Node> defaultGraphs ;
    // The graphs making up the default graph seen as <urn:x-arq:DefaultGraph>
    // Often the same as above; not if union-of-named-graphs visible
    private Set<Node> defaultGraphsReal ;
    private Set<Node> namedGraphs ;

    /** Apply the dynamic dataset transformation: rewrite the algebra into a form that uses
     *  the dataset description for a dynamic choice of graphs. 
     */
    public static Op transform(Query query, Op op)
    {
        if ( ! query.hasDatasetDescription() )
            return op ;
        Set<Node> defaultGraphs = NodeUtils.convertToNodes(query.getGraphURIs()) ;
        Set<Node> namedGraphs = NodeUtils.convertToNodes(query.getNamedGraphURIs()) ;
        Transform t = new TransformDynamicDataset_Imperfect(defaultGraphs, namedGraphs, false) ; // false??
        Op op2 = Transformer.transform(t, op) ;
        return op2 ;
    }
   
    public TransformDynamicDataset_Imperfect(Set<Node> defaultGraphs, Set<Node> namedGraphs, boolean defaultGraphIncludesNamedGraphUnion)
    {
        this.defaultGraphs = defaultGraphs ;
        this.defaultGraphsReal = defaultGraphs ;
        this.namedGraphs = namedGraphs ;
        if ( defaultGraphIncludesNamedGraphUnion )
        {
            // Named graph union.
            this.defaultGraphs = new HashSet<Node>() ;
            this.defaultGraphs.addAll(defaultGraphs) ;
            this.defaultGraphs.addAll(namedGraphs) ;
        }
    }
   
    @Override
    public Op transform(OpBGP op)
    {
        // Bad - assume we work on the quad form.
        // Otherwise need to know the active graph at this point
        // toQuadForm transformation.
        throw new ARQException("Unexpected use of BGP in for a dynamic dataset") ;
        //return super.transform(op) ;
    }
   
    @Override
    public Op transform(OpPath op)
    {
        Log.warn(this, "Paths in dynamic datasets queries not supported yet") ;
        //throw new ARQException("Unexpected use of Path in for a dynamic dataset") ;
        return super.transform(op) ;
    }
   
//    @Override
//    public Op transform(OpTriple opTriple)
//    {
//        return super.transform(opTriple) ;
//    }
   
    @Override
    public Op transform(OpQuadPattern opQuadPattern)
    {
        Node gn = opQuadPattern.getGraphNode() ;

        if ( Quad.isDefaultGraphGenerated(gn) ) 
            // Quad pattern directed at the default graph (not by explicit name).
            return patternOver(defaultGraphs, opQuadPattern.getBasicPattern()) ;

        if ( gn.equals(Quad.defaultGraphIRI) )
            // <urn:x-arq:DefaultGraph>
            return patternOver(defaultGraphsReal, opQuadPattern.getBasicPattern()) ;
       
        if ( Quad.isUnionGraph(gn) ) 
            // <urn:x-arq:UnionGraph>
            // Quad pattern directed at the union of (visible) named graphs
            return patternOver(namedGraphs, opQuadPattern.getBasicPattern()) ;

        if ( gn.isVariable() )
        {
            // GRAPH ?g but no named graphs.
            if (namedGraphs.size() == 0 )
                return OpNull.create() ;
           
            Var v = Var.alloc(gn) ;
            Op union = null ;
            for ( Node n : namedGraphs )
            {
                Binding b = BindingFactory.binding(v, n) ;
                Op x2 = QC.substitute(opQuadPattern, b) ;
                Op op = OpAssign.assign(x2, v, NodeValue.makeNode(n)) ;
                union = OpUnion.create(union, op) ;
            }
            return union ;
        }

        // Not a variable.
        if ( ! namedGraphs.contains(gn) )
            // No match.
            return OpNull.create() ;
        // Nothing to do.
        return super.transform(opQuadPattern) ;
    }

    // Generate quad algebra that accesses the set of graphs as a single graph (including duplicate surpression).
    private Op patternOver(Set<Node> graphs, BasicPattern basicPattern)
    {
        if ( basicPattern.size() == 0 )
            return OpTable.unit() ;
       
        if ( graphs.size() == 0 )
        {
            // No graphs => no results.
            return OpNull.create() ;
        }
       
        // WRONG - must be per triple pattern.
        // distinct needed each step?
       
//        Op union = null ;
//        
//        for ( Node n : graphs )
//        {
//            Op pattern = new OpQuadPattern(n, basicPattern) ;
//            union = OpUnion.create(union, pattern) ;
//        }
        if ( graphs.size() == 1 )
        {
            // Simple rewrite.
            Node n = graphs.iterator().next() ;
            return new OpQuadPattern(n, basicPattern) ;
        }
           
        OpSequence opSeq = OpSequence.create() ;
       
        for ( Triple t : basicPattern )
        {
            // One expansion for each triple pattern.
            Op union = null ;
            for ( Node n : graphs )
            {
                BasicPattern bp = new BasicPattern() ;
                bp.add(t) ;
                Op pattern = new OpQuadPattern(n, bp) ;
                union = OpUnion.create(union, pattern) ;
            }
            opSeq.add(union) ;
        }
       
        // More than one graph - make distinct
        return new OpDistinct(opSeq) ;
    }

    @Override
    public Op transform(OpDatasetNames opDatasetNames)
    {
        Node gn = opDatasetNames.getGraphNode() ;
        if ( gn.isVariable() )
        {
            // Answer is a table.
            Table t = TableFactory.create() ;
            Var v = Var.alloc(gn) ;
            for ( Node n : namedGraphs )
            {
                Binding b = BindingFactory.binding(v, n) ;
                t.addBinding(b) ;
            }
            return OpTable.create(t) ;
        }
        // Not a variable.
        if ( ! namedGraphs.contains(gn) )
            // No match.
            return OpNull.create() ;
        // Nothing to do.
        return super.transform(opDatasetNames) ;
    }

    @Override
    public Op transform(OpGraph opGraph, Op x)
    {
        // We work on quad forms so this does not occur. 
        // But do it anyway, for completeness and for any later chnages.
       
        // What we need to do is a sequence whereby we loop over the namedGraphs
        // and try each possibility.
       
        Node gn = opGraph.getNode() ;
        if ( Quad.isDefaultGraph(gn) )
        {
            System.err.println("<Cough/>") ;
        }
       
       
        if ( namedGraphs.size() == 0 )
            return OpNull.create() ;
       
        if ( gn.isVariable() )
        {
            Op union = null ;
            Var v = Var.alloc(gn) ;
           
            for ( Node n : namedGraphs )
            {
                /* Graph evaluation is defined as:
                 * foreach IRI i in D
                 *    R := Union(R, Join( eval(D(D[i]), P) , Ω(?var->i) )
                 */
                // Do before join classification and optimization.
                Op op = OpTable.create(new Table1(v, n)) ;
                op = OpJoin.create(op, x) ;
                op = new OpGraph(n, op) ;
                // Don't need an assign.  The table did that.
                // op = OpAssign.assign(op, v, NodeValue.makeNode(n)) ;
                union = OpUnion.create(union, op) ;
            }
            return union ;
        }

        // Not a variable.
        if ( ! namedGraphs.contains(gn) )
            // No match.
            return OpNull.create() ;
        // Nothing to do.
        return super.transform(opGraph, x) ;
    }
   
}
TOP

Related Classes of com.hp.hpl.jena.tdb.migrate.TransformDynamicDataset_Imperfect

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.