com.bigdata.rdf.sparql.ast.ASTBase 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
*/
/*
* Created on Aug 25, 2011
*/
package com.bigdata.rdf.sparql.ast;
import java.util.Map;
import java.util.Properties;
import com.bigdata.bop.BOp;
import com.bigdata.bop.ModifiableBOpBase;
import com.bigdata.bop.PipelineOp;
import com.bigdata.rdf.sparql.ast.eval.AST2BOpContext;
import com.bigdata.rdf.sparql.ast.eval.AST2BOpUtility;
import com.bigdata.rdf.sparql.ast.explainhints.ExplainHints;
import com.bigdata.rdf.sparql.ast.explainhints.IExplainHint;
import com.bigdata.rdf.sparql.ast.optimizers.ASTQueryHintOptimizer;
import com.bigdata.rdf.sparql.ast.optimizers.IASTOptimizer;
/**
* Base class for the AST.
*
* @author Bryan Thompson
* @version $Id$
*/
public class ASTBase extends ModifiableBOpBase {
/**
*
*/
private static final long serialVersionUID = 1L;
public interface Annotations extends ModifiableBOpBase.Annotations {
/**
* An optional {@link Properties} object specifying query hints which
* apply to this AST node.
*
* The relationship between SPARQL level query hints, the annotations on
* the {@link ASTBase} and {@link PipelineOp} nodes is a bit complex,
* and this {@link Properties} object is a bit complex. Briefly, this
* {@link Properties} object contains property values which will be
* applied (copied) onto generated {@link PipelineOp}s while annotations
* on the {@link ASTBase} nodes are interpreted by {@link IASTOptimizer}
* s and {@link AST2BOpUtility}. SPARQL level query hints map into one
* or another of these things, or may directly set attributes on the
* {@link AST2BOpContext}.
*
* @see ASTQueryHintOptimizer
* @see
* Clean up query hints
*/
String QUERY_HINTS = "queryHints";
/**
* An optional {@link ExplainHints} object specifying hints to be
* exposed to the user when requesting an explanation of the query.
*/
String EXPLAIN_HINTS = "explainHints";
}
/**
* Constructor required for {@link com.bigdata.bop.BOpUtility#deepCopy(FilterNode)}.
*/
public ASTBase(final ASTBase op) {
super(op);
}
/**
* Required shallow copy constructor.
*/
public ASTBase(final BOp[] args, final Map annotations) {
super(args, annotations);
}
/**
* Return the query hints for this AST node.
*
* @return The query hints -or- null
if none have been
* declared.
*/
public Properties getQueryHints() {
return (Properties) getProperty(Annotations.QUERY_HINTS);
}
/**
* Return the explain hints associated with this AST node
*
* @return The explain hints -or- null
if none have been
* declared.
*/
public ExplainHints getExplainHints() {
return (ExplainHints) getProperty(Annotations.EXPLAIN_HINTS);
}
/**
* Return the value of the query hint.
*
* @param name
* The name of the query hint.
*
* @return The value of the query hint and null
if the query
* hint is not defined.
*/
public String getQueryHint(final String name) {
return getQueryHint(name, null/*defaultValue*/);
}
/**
* Return the value of the query hint.
*
* @param name
* The name of the query hint.
* @param defaultValue
* The default value to use if the query hint is not defined.
*
* @return The value of the query hint and defaultValue if the query
* hint is not defined.
*/
public String getQueryHint(final String name, final String defaultValue) {
final Properties queryHints = (Properties) getProperty(Annotations.QUERY_HINTS);
if (queryHints == null)
return defaultValue;
return queryHints.getProperty(name, defaultValue);
}
/**
* Return the boolean value of the query hint.
*
* @param name
* The name of the query hint.
* @param defaultValue
* The default value to use if the query hint is not defined.
*/
public boolean getQueryHintAsBoolean(final String name,
final String defaultValue) {
return Boolean.valueOf(getQueryHint(name, defaultValue));
}
/**
* Return the boolean value of the query hint.
*
* @param name
* The name of the query hint.
* @param defaultValue
* The default value to use if the query hint is not defined.
*/
public boolean getQueryHintAsBoolean(final String name,
final boolean defaultValue) {
return Boolean.valueOf(getQueryHint(name,
Boolean.toString(defaultValue)));
}
/**
* Return the Integer value of the query hint.
*
* @param name
* The name of the query hint.
* @param defaultValue
* The default value to use if the query hint is not defined.
*/
public Integer getQueryHintAsInteger(final String name,
final Integer defaultValue) {
return Integer.valueOf(getQueryHint(name,
Integer.toString(defaultValue)));
}
/**
* Set the query hints.
*
* @param queryHints
* The query hints (may be null
).
*
* @see QueryHints
*/
public void setQueryHints(final Properties queryHints) {
setProperty(Annotations.QUERY_HINTS, queryHints);
}
/**
* Add an explain hint to the query.
*
* @param explainHint the hint to add, ignored if null
*/
public void addExplainHint(IExplainHint explainHint) {
if (explainHint==null) {
return;
}
// add the hint, creating a new object if required
final ExplainHints explainHints = getExplainHints();
if (explainHints==null) {
setProperty(Annotations.EXPLAIN_HINTS, new ExplainHints(explainHint));
} else {
explainHints.addExplainHint(explainHint);
}
}
/**
* Set a query hint.
*
* @param name
* The property name for the query hint.
* @param value
* The property value for the query hint.
*/
public void setQueryHint(final String name, final String value) {
if (name == null)
throw new IllegalArgumentException();
if (value == null)
throw new IllegalArgumentException();
Properties queryHints = getQueryHints();
if (queryHints == null) {
// Lazily allocate the map.
setProperty(Annotations.QUERY_HINTS, queryHints = new Properties());
}
queryHints.setProperty(name, value);
}
/**
* Replace all occurrences of the old value with the new value in both the
* arguments and annotations of this operator (recursive). A match is
* identified by reference {@link #equals(Object)}.
*
* @param oldVal
* The old value.
* @param newVal
* The new value.
*
* @return The #of changes made.
*/
public int replaceAllWith(final BOp oldVal, final BOp newVal) {
int n = 0;
final int arity = arity();
for (int i = 0; i < arity; i++) {
final BOp child = get(i);
if (child != null && child.equals(oldVal)) {
setArg(i, newVal);
n++;
}
if (child instanceof ASTBase) {
n += ((ASTBase) child).replaceAllWith(oldVal, newVal);
}
}
for (Map.Entry e : annotations().entrySet()) {
if (e.getValue() instanceof ASTBase) {
n += ((ASTBase) e.getValue()).replaceAllWith(oldVal, newVal);
}
}
return n;
}
}