/* * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2006. * * Licensed under the Aduna BSD-style license. */ package org.openrdf.query.parser.serql; import java.util.LinkedHashSet; import java.util.Set; import org.openrdf.query.MalformedQueryException; import org.openrdf.query.parser.serql.ast.ASTProjectionElem; import org.openrdf.query.parser.serql.ast.ASTQueryContainer; import org.openrdf.query.parser.serql.ast.ASTSelect; import org.openrdf.query.parser.serql.ast.ASTSelectQuery; import org.openrdf.query.parser.serql.ast.ASTVar; import org.openrdf.query.parser.serql.ast.ASTWhere; import org.openrdf.query.parser.serql.ast.SyntaxTreeBuilderTreeConstants; import org.openrdf.query.parser.serql.ast.VisitorException; /** * Processes 'wildcard' projections, making them explicit by adding projection * elements with the appropriate variable nodes to them. * * @author Arjohn Kampman */ class WildcardProjectionProcessor extends ASTVisitorBase { public static void process(ASTQueryContainer qc) throws MalformedQueryException { try { qc.jjtAccept(new WildcardProjectionProcessor(), null); } catch (VisitorException e) { throw new MalformedQueryException(e.getMessage(), e); } } @Override public Object visit(ASTSelect node, Object data) throws VisitorException { if (node.isWildcard()) { // Collect all variables used in the body of the select query ProjectionVariableCollector visitor = new ProjectionVariableCollector(); node.jjtGetParent().jjtAccept(visitor, null); for (String varName : visitor.getVariableNames()) { ASTProjectionElem projElemNode = new ASTProjectionElem( SyntaxTreeBuilderTreeConstants.JJTPROJECTIONELEM); node.jjtAppendChild(projElemNode); projElemNode.jjtSetParent(node); ASTVar varNode = new ASTVar(SyntaxTreeBuilderTreeConstants.JJTVAR); varNode.setName(varName); projElemNode.jjtAppendChild(varNode); varNode.jjtSetParent(projElemNode); } node.setWildcard(false); } return data; } /*-----------------------------------------* * Inner class ProjectionVariableCollector * *-----------------------------------------*/ /** * Collects variable names for 'wildcard' projections. An instance of this * class should be supplied to a {@link ASTSelectQuery} node. When done, the * collected variable names can be acquired by calling * {@link #getVariableNames}. */ private static class ProjectionVariableCollector extends ASTVisitorBase { private Set<String> variableNames = new LinkedHashSet<String>(); public Set<String> getVariableNames() { return variableNames; } @Override public Object visit(ASTWhere node, Object data) throws VisitorException { // Do not visit where clauses return data; } @Override public Object visit(ASTVar node, Object data) throws VisitorException { variableNames.add(node.getName()); return super.visit(node, data); } } }