01: /*
02: * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2006.
03: *
04: * Licensed under the Aduna BSD-style license.
05: */
06: package org.openrdf.query.parser.serql;
07:
08: import java.util.LinkedHashSet;
09: import java.util.Set;
10:
11: import org.openrdf.query.MalformedQueryException;
12: import org.openrdf.query.parser.serql.ast.ASTProjectionElem;
13: import org.openrdf.query.parser.serql.ast.ASTQueryContainer;
14: import org.openrdf.query.parser.serql.ast.ASTSelect;
15: import org.openrdf.query.parser.serql.ast.ASTSelectQuery;
16: import org.openrdf.query.parser.serql.ast.ASTVar;
17: import org.openrdf.query.parser.serql.ast.ASTWhere;
18: import org.openrdf.query.parser.serql.ast.SyntaxTreeBuilderTreeConstants;
19: import org.openrdf.query.parser.serql.ast.VisitorException;
20:
21: /**
22: * Processes 'wildcard' projections, making them explicit by adding projection
23: * elements with the appropriate variable nodes to them.
24: *
25: * @author Arjohn Kampman
26: */
27: class WildcardProjectionProcessor extends ASTVisitorBase {
28:
29: public static void process(ASTQueryContainer qc)
30: throws MalformedQueryException {
31: try {
32: qc.jjtAccept(new WildcardProjectionProcessor(), null);
33: } catch (VisitorException e) {
34: throw new MalformedQueryException(e.getMessage(), e);
35: }
36: }
37:
38: @Override
39: public Object visit(ASTSelect node, Object data)
40: throws VisitorException {
41: if (node.isWildcard()) {
42: // Collect all variables used in the body of the select query
43: ProjectionVariableCollector visitor = new ProjectionVariableCollector();
44: node.jjtGetParent().jjtAccept(visitor, null);
45:
46: for (String varName : visitor.getVariableNames()) {
47: ASTProjectionElem projElemNode = new ASTProjectionElem(
48: SyntaxTreeBuilderTreeConstants.JJTPROJECTIONELEM);
49: node.jjtAppendChild(projElemNode);
50: projElemNode.jjtSetParent(node);
51:
52: ASTVar varNode = new ASTVar(
53: SyntaxTreeBuilderTreeConstants.JJTVAR);
54: varNode.setName(varName);
55: projElemNode.jjtAppendChild(varNode);
56: varNode.jjtSetParent(projElemNode);
57: }
58:
59: node.setWildcard(false);
60: }
61:
62: return data;
63: }
64:
65: /*-----------------------------------------*
66: * Inner class ProjectionVariableCollector *
67: *-----------------------------------------*/
68:
69: /**
70: * Collects variable names for 'wildcard' projections. An instance of this
71: * class should be supplied to a {@link ASTSelectQuery} node. When done, the
72: * collected variable names can be acquired by calling
73: * {@link #getVariableNames}.
74: */
75: private static class ProjectionVariableCollector extends
76: ASTVisitorBase {
77:
78: private Set<String> variableNames = new LinkedHashSet<String>();
79:
80: public Set<String> getVariableNames() {
81: return variableNames;
82: }
83:
84: @Override
85: public Object visit(ASTWhere node, Object data)
86: throws VisitorException {
87: // Do not visit where clauses
88: return data;
89: }
90:
91: @Override
92: public Object visit(ASTVar node, Object data)
93: throws VisitorException {
94: variableNames.add(node.getName());
95: return super.visit(node, data);
96: }
97: }
98: }
|