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