All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.bigdata.rdf.sail.sparql.GroupGraphPattern Maven / Gradle / Ivy

/*

Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016.  All rights reserved.

Contact:
     SYSTAP, LLC DBA Blazegraph
     2501 Calvert ST NW #106
     Washington, DC 20008
     [email protected]

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; version 2 of the License.

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, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
/* Portions of this code are:
 * 
 * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007.
 *
 * Licensed under the Aduna BSD-style license.
 */
package com.bigdata.rdf.sail.sparql;

import java.util.LinkedList;
import java.util.List;

import org.apache.log4j.Logger;
import org.openrdf.query.algebra.StatementPattern;
import org.openrdf.query.algebra.StatementPattern.Scope;

import com.bigdata.bop.BOp;
import com.bigdata.bop.BOpUtility;
import com.bigdata.rdf.sparql.ast.FilterNode;
import com.bigdata.rdf.sparql.ast.GroupNodeBase;
import com.bigdata.rdf.sparql.ast.IGroupMemberNode;
import com.bigdata.rdf.sparql.ast.JoinGroupNode;
import com.bigdata.rdf.sparql.ast.PathNode;
import com.bigdata.rdf.sparql.ast.PropertyPathNode;
import com.bigdata.rdf.sparql.ast.QuadData;
import com.bigdata.rdf.sparql.ast.StatementPatternNode;
import com.bigdata.rdf.sparql.ast.TermNode;
import com.bigdata.rdf.sparql.ast.UnionNode;
import com.bigdata.rdf.sparql.ast.ValueExpressionNode;

/**
 * A group graph pattern consisting of (required and optional) tuple
 * expressions, binding assignments and boolean constraints.
 * 
 * @author Arjohn Kampman
 * @author Bryan Thompson
 * @openrdf
 */
class GroupGraphPattern {

    private static final Logger log = Logger.getLogger(GroupGraphPattern.class);
    
    private boolean invalid = false;
    
    private void assertValid() {
        if (invalid)
            throw new IllegalStateException();
    }

    /**
     * The context of this graph pattern.
     */
    private TermNode context;

    /**
     * The StatementPattern-scope of this graph pattern.
     */
    private StatementPattern.Scope spScope = StatementPattern.Scope.DEFAULT_CONTEXTS;

    /**
     * This is all direct children of the group.
     */
    private final List children = new LinkedList();

    /**
     * Creates a new graph pattern.
     */
    public GroupGraphPattern() {
    }
    
    /**
     * Creates a new graph pattern that inherits the context and scope from a
     * parent graph pattern.
     */
    public GroupGraphPattern(final GroupGraphPattern parent) {
        this(parent.context, parent.spScope);
    }
    
    /**
     * Creates a new graph pattern in the given context and scope.
     */
    public GroupGraphPattern(TermNode context, Scope spScope) {
       this.context = context;
       this.spScope = spScope;
    }


    public void setContextVar(final TermNode context) {

        assertValid();
        
        this.context = context;
        
    }

    public TermNode getContext() {
        
        assertValid();
        
        return context;
        
    }

//    /**
//     * The #of things in the group.
//     */
//    public int size() {
//        
//        return children.size();
//        
//    }
//
//    /**
//     * Return the child at that index.
//     * 
//     * @param index
//     *            The index.
//     *            
//     * @return The child.
//     */
//    public IGroupMemberNode get(final int index) {
//     
//        return children.get(index);
//        
//    }
    
    public void setStatementPatternScope(final StatementPattern.Scope spScope) {
        
        assertValid();
        
        this.spScope = spScope;
        
    }

    public StatementPattern.Scope getStatementPatternScope() {
        
        assertValid();
        
        return spScope;
        
    }

    public void add(final IGroupMemberNode child) {
        
        assertValid();
        
        if (log.isInfoEnabled())
            log.info("child=" + BOpUtility.toString((BOp)child));

        children.add(child);

    }

    public void addSP(final TermNode s, final TermNode p, final TermNode o) {

        assertValid();

        if (log.isInfoEnabled())
            log.info("pattern= ( " + s + " " + p + " " + o + " )");

        // Fill in the inherited context and scope.
        children.add(new StatementPatternNode(s, p, o, context, spScope));

    }
    
    public void addPP(final TermNode s, final PathNode p, final TermNode o) {
    	
        assertValid();

        if (log.isInfoEnabled())
            log.info("pattern= ( " + s + " " + p + " " + o + " )");

        // Fill in the inherited context and scope.
        children.add(new PropertyPathNode(s, p, o, context, spScope));
    	
    }

    public void addSP(final StatementPatternNode sp) {

        assertValid();

        if (log.isInfoEnabled())
            log.info("pattern=" + sp);

        // Fill in the inherited context and scope.
//        final StatementPatternNode t = new StatementPatternNode(sp.s(), sp.p(),
//                sp.o(), context, spScope);
		
        if (context != null) {
		
        		sp.setC(context);
        	
		}
        
        sp.setScope(spScope);

        children.add(sp);

    }
    
    public void addConstraint(final ValueExpressionNode constraint) {

        assertValid();

        if (log.isInfoEnabled())
            log.info("constraint=" + constraint);

        children.add(new FilterNode(constraint));

    }

    /**
     * Attach the data to the group node.
     * 
     * @param groupNode
     *            The group node.
     * 
     * @return The group node supplied by the caller with the data attached.
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public  T buildGroup(final T groupNode) {

        assertValid();

        // mark the GroupGraphPattern as consumed.
        invalid = true;

        final boolean isUnion = groupNode instanceof UnionNode;

        if (isUnion) {

            /*
             * If we are building a union node, then we will (A) flatten nested
             * UNIONs into a single UNION; and (b) wrap any non-JoinGroupNode
             * with a JoinGroupNode.
             */
            for (IGroupMemberNode child : children) {

                if(child instanceof JoinGroupNode) {
                    
                    groupNode.addChild(child);
                    
                } else if(child instanceof UnionNode) {
                    
                    /*
                     * Lift children out of the child UNION.
                     */
                    final UnionNode childUnion = (UnionNode) child;
                    
                    for(IGroupMemberNode child2 : childUnion) {
                        
                        groupNode.addChild(child2);
                        
                    }
                    
                } else {
                
                    groupNode.addChild(new JoinGroupNode(child));
                    
                }
                
            }
            
        } else {

            for (IGroupMemberNode child : children) {

                if (child instanceof QuadData
                        && groupNode instanceof JoinGroupNode) {
                    
                    /*
                     * We need to flatten out the QuadData when it appears
                     * within a WHERE clause for a DELETE WHERE shortcut.
                     * 
                     * @see https://sourceforge.net/apps/trac/bigdata/ticket/568
                     * (DELETE WHERE fails with Java AssertionError)
                     */
                    
                    final JoinGroupNode newGroup = new JoinGroupNode();

                    ((QuadData) child).flatten(newGroup);

                    // A statement pattern node from the nested GRAPH group.
                    // They will all share the same context.
                    
                    final StatementPatternNode sp = (StatementPatternNode) newGroup
                            .get(0);

                    // The context for the SPs in that GRAPH group.
                    final TermNode context = (TermNode) sp.get(3);
                    
                    // Must be defined.
                    assert context != null;
                    
                    // Must be a named graph scope.
                    assert sp.getScope() == Scope.NAMED_CONTEXTS;
                    
                    // Set on the new group.
                    newGroup.setContext(context);

                    // Add the new group to the outer group.
                    groupNode.addChild(newGroup);
                    
                } else {
                
                    groupNode.addChild(child);

                }
                
            }

        }
        
        return groupNode;

    }
    
    /**
     * Useful when the caller knows that the children will be a single
     * {@link JoinGroupNode}.
     * 
     * @return That {@link JoinGroupNode}.
     */
    public JoinGroupNode getSingletonGroup() {
        
        assertValid();
        
        invalid = true;

        if (children.size() != 1)
            throw new RuntimeException("Expecting one child, not "
                    + children.size());
        
        return (JoinGroupNode) children.get(0);
        
    }

    public String toString() {
        final StringBuilder sb = new StringBuilder();
        sb.append(super.toString() + "{");
        sb.append("context=" + context);
        sb.append(", scope=" + spScope);
        sb.append(", children=[");
        boolean first = true;
        for (IGroupMemberNode child : children) {
            if (!first)
                sb.append(", ");
            sb.append(child);
            first = false;
        }
        sb.append("]}");
        return sb.toString();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy