/*
* Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007.
*
* Licensed under the Aduna BSD-style license.
*/
package com.bigdata.rdf.sail.sparql;
import info.aduna.net.ParsedURI;
import org.openrdf.query.MalformedQueryException;
import com.bigdata.rdf.sail.sparql.ast.ASTBaseDecl;
import com.bigdata.rdf.sail.sparql.ast.ASTDeleteData;
import com.bigdata.rdf.sail.sparql.ast.ASTIRI;
import com.bigdata.rdf.sail.sparql.ast.ASTIRIFunc;
import com.bigdata.rdf.sail.sparql.ast.ASTInsertData;
import com.bigdata.rdf.sail.sparql.ast.ASTOperationContainer;
import com.bigdata.rdf.sail.sparql.ast.ASTServiceGraphPattern;
import com.bigdata.rdf.sail.sparql.ast.ASTUnparsedQuadDataBlock;
import com.bigdata.rdf.sail.sparql.ast.VisitorException;
/**
* Resolves relative URIs in a query model using either an external base URI or
* using the base URI specified in the query model itself. The former takes
* precedence over the latter.
*
* @author Arjohn Kampman
* @openrdf
*/
public class BaseDeclProcessor {
/**
* Resolves relative URIs in the supplied query model using either the
* specified <tt>externalBaseURI</tt> or, if this parameter is
* <tt>null</tt>, the base URI specified in the query model itself.
*
* @param qc
* The query model to resolve relative URIs in.
* @param externalBaseURI
* The external base URI to use for resolving relative URIs, or
* <tt>null</tt> if the base URI that is specified in the query
* model should be used.
* @throws IllegalArgumentException
* If an external base URI is specified that is not an absolute URI.
* @throws MalformedQueryException
* If the base URI specified in the query model is not an absolute
* URI.
*/
public static void process(ASTOperationContainer qc, String externalBaseURI)
throws MalformedQueryException
{
ParsedURI parsedBaseURI = null;
// Use the query model's own base URI, if available
ASTBaseDecl baseDecl = qc.getBaseDecl();
if (baseDecl != null) {
parsedBaseURI = new ParsedURI(baseDecl.getIRI());
if (!parsedBaseURI.isAbsolute()) {
throw new MalformedQueryException("BASE IRI is not an absolute IRI: " + externalBaseURI);
}
}
else if (externalBaseURI != null) {
// Use external base URI if the query doesn't contain one itself
parsedBaseURI = new ParsedURI(externalBaseURI);
if (!parsedBaseURI.isAbsolute()) {
throw new IllegalArgumentException("Supplied base URI is not an absolute IRI: " + externalBaseURI);
}
}
else {
// FIXME: use the "Default Base URI"?
}
if (parsedBaseURI != null) {
ASTUnparsedQuadDataBlock dataBlock = null;
if (qc.getOperation() instanceof ASTInsertData) {
ASTInsertData insertData = (ASTInsertData)qc.getOperation();
dataBlock = insertData.jjtGetChild(ASTUnparsedQuadDataBlock.class);
}
else if (qc.getOperation() instanceof ASTDeleteData) {
ASTDeleteData deleteData = (ASTDeleteData)qc.getOperation();
dataBlock = deleteData.jjtGetChild(ASTUnparsedQuadDataBlock.class);
}
if (dataBlock != null) {
final String baseURIDeclaration = "BASE <" + parsedBaseURI + ">";
dataBlock.setDataBlock(baseURIDeclaration + dataBlock.getDataBlock());
}
else {
RelativeIRIResolver visitor = new RelativeIRIResolver(parsedBaseURI);
try {
qc.jjtAccept(visitor, null);
}
catch (VisitorException e) {
throw new MalformedQueryException(e);
}
}
}
}
private static class RelativeIRIResolver extends ASTVisitorBase {
private ParsedURI parsedBaseURI;
public RelativeIRIResolver(ParsedURI parsedBaseURI) {
this.parsedBaseURI = parsedBaseURI;
}
@Override
public Object visit(ASTIRI node, Object data)
throws VisitorException
{
ParsedURI resolvedURI = parsedBaseURI.resolve(node.getValue());
node.setValue(resolvedURI.toString());
return super.visit(node, data);
}
@Override
public Object visit(ASTIRIFunc node, Object data)
throws VisitorException
{
node.setBaseURI(parsedBaseURI.toString());
return super.visit(node, data);
}
@Override
public Object visit(ASTServiceGraphPattern node, Object data)
throws VisitorException
{
node.setBaseURI(parsedBaseURI.toString());
return super.visit(node, data);
}
}
}