/* // $Id: //guest/julian_hyde/saffron/src/main/openjava/ptree/util/QueryExpander.java#1 $ // (C) Copyright 2001 Broadbase Software, Inc. // jhyde, 24 March, 2001 */ package openjava.ptree.util; import openjava.mop.*; import openjava.ptree.*; import openjava.tools.parser.ParserConstants; import java.util.HashSet; /** * <code>QueryExpander</code> is a {@link ParseTreeVisitor} which, as it passes * over a parse tree, converts {@link QueryExpression}s into regular java * constructs. * * <p>The non-abstract derived class {@link saffron.SaffronQueryExpander} does this * by converting the expression to a tree of {@link saffron.Rel} nodes, and using * an optimizer ({@link saffron.Planner}) to choose the optimal java * implementation.</p> **/ public abstract class QueryExpander extends ScopeHandler { public QueryExpander(Environment env) { super(env); } public Expression evaluateDown( QueryExpression p ) throws ParseTreeException { super.evaluateDown(p); return expandExpression(p); } private boolean isRelational(Expression p) { if (p instanceof QueryExpression) { return true; } else if (p instanceof BinaryExpression) { switch (((BinaryExpression) p).getOperator()) { case BinaryExpression.IN: case BinaryExpression.UNION: case BinaryExpression.INTERSECT: case BinaryExpression.REL_MINUS: return true; default: return false; } } else if (p instanceof UnaryExpression) { switch (((UnaryExpression) p).getOperator()) { case UnaryExpression.EXISTS: return true; default: return false; } } else if (p instanceof MethodCall) { // A call to the method saffron.Connection.contentsAsArray(String) // is relational. MethodCall methodCall = (MethodCall) p; String name = methodCall.getName(); if (!name.equals("contentsAsArray")) { return false; } Expression refexpr = methodCall.getReferenceExpr(); if (refexpr == null) { return false; } Environment env = getEnvironment(); OJClass reftype = Toolbox.getType(env, refexpr); if (!Toolbox.clazzConnection.isAssignableFrom(reftype)) { return false; } return true; } else { return false; } } public Expression evaluateDown(CastExpression p) throws ParseTreeException { Expression exp = p.getExpression(); if (isRelational(exp)) { return expandExpression(p); } else { return super.evaluateDown(p); } } /** * Expand 'for (<<variable>> in <<query>>) ...'. */ public Statement evaluateDown(ForStatement p) throws ParseTreeException { if (p.getQuery() == null) { return super.evaluateDown(p); } else { return expandForIn( new Variable(p.getVariable()), p.getQuery(), p.getStatements()); } } /** * Expands <code>in</code> <code>union</code>, <code>minus</code>, and * <code>intersect</code>. **/ public Expression evaluateDown(BinaryExpression p) throws ParseTreeException { switch (p.getOperator()) { case BinaryExpression.IN: case BinaryExpression.UNION: case BinaryExpression.INTERSECT: case BinaryExpression.REL_MINUS: return expandExpression(p); default: return super.evaluateDown(p); } } /** * Expands <code>exists</code>. **/ public Expression evaluateDown(UnaryExpression p) throws ParseTreeException { switch (p.getOperator()) { case UnaryExpression.EXISTS: return expandExpression(p); default: return super.evaluateDown(p); } } /** * Expands <code>connection.contentsAsArray("name")</code>, which was * probably generated by expanding <code>connection.name</code>. **/ public Expression evaluateDown(MethodCall p) throws ParseTreeException { if (isRelational(p)) { // The call "connection.contentsAsArray("name")" will become // "select from something" return expandExpression(p); } return super.evaluateDown(p); } public CompilationUnit evaluateUp(CompilationUnit p) throws ParseTreeException { // try { // SyntheticClassCollector classCollector = new // SyntheticClassCollector(getEnvironment()); // classCollector.visit(p); // SyntheticClass[] classes = classCollector.getClasses(); // ClassDeclaration publicClassDecl = p.getPublicClass(); // for (int i = 0; i < classes.length; i++) { // SyntheticClass clazz = classes[i]; // publicClassDecl.getBody().add(clazz.decl); // } // } finally { return super.evaluateUp(p); // } } /* boolean isRelational(Expression exp) { if (exp instanceof QueryExpression) { return true; } else if (exp instanceof BinaryExpression) { BinaryExpression p = (BinaryExpression) exp; switch (p.getOperator()) { case BinaryExpression.IN: case BinaryExpression.UNION: case BinaryExpression.REL_MINUS: case BinaryExpression.INTERSECT: return true; default: return false; } } else if (exp instanceof UnaryExpression) { UnaryExpression p = (UnaryExpression) exp; switch (p.getOperator()) { case UnaryExpression.EXISTS: return true; default: return false; } } else { return false; } } */ /** * Converts an {@link Expression} into a java expression which returns an * array. **/ protected abstract Expression expandExpression(Expression p); /** * Converts an {@link Expression} of the form <code>for (<i>variable</i> in * <i>exp</i>) { <i>body</i> }</code> into a regular java {@link * openjava.ptree.Statement}. **/ protected abstract Statement expandForIn( Variable var, Expression p, StatementList body); /** * <code>SyntheticClassCollector</code> finds all {@link SyntheticClass}es * referenced via a {@link TypeName} in a parse tree. */ private static class SyntheticClassCollector extends ScopeHandler { private HashSet classSet = new HashSet(); SyntheticClassCollector(Environment env) { super(env); } public TypeName evaluateUp(TypeName p) throws ParseTreeException { try { Environment env = getEnvironment(); String typeName = p.getName(); String qualifiedName = env.toQualifiedName(typeName); SyntheticClass syntheticClazz = (SyntheticClass) SyntheticClass.mapQualifiedClassName2SyntheticClass.get( qualifiedName); if (syntheticClazz != null) { classSet.add(syntheticClazz); } } finally { return super.evaluateUp(p); } } SyntheticClass[] getClasses() { return (SyntheticClass[]) classSet.toArray(new SyntheticClass[0]); } }; } // End QueryExpander.java
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#3 | 1748 | Julian Hyde |
saffron: convert unit tests to JUnit; add CallingConvention.ITERABLE; lots of other stuff; release 0.1. |
||
#2 | 1474 | Julian Hyde |
saffron: Aggregations are working. Renamed 'aggregator' to 'aggregation'. |
||
#1 | 1467 | Julian Hyde |
saffron: First saffron check-in; incorporate my changes to openjava. |