1 package com.jofti.parser; 2 3 import java.io.IOException ; 4 import java.io.Reader ; 5 import java.io.StringReader ; 6 import java.util.ArrayList ; 7 import java.util.HashMap ; 8 import java.util.Iterator ; 9 import java.util.LinkedHashMap ; 10 import java.util.List ; 11 import java.util.Map ; 12 import java.util.Stack ; 13 14 import org.apache.commons.logging.Log; 15 import org.apache.commons.logging.LogFactory; 16 17 import antlr.collections.AST; 18 19 import com.jofti.api.IndexQuery; 20 import com.jofti.core.INameSpaceAware; 21 import com.jofti.core.IParsedQuery; 22 import com.jofti.core.IPredicate; 23 import com.jofti.exception.JoftiException; 24 import com.jofti.introspect.ClassIntrospector; 25 import com.jofti.parser.sql.SQLQueryParser; 26 import com.jofti.query.EJBQuery; 27 import com.jofti.query.SQLQuery; 28 import com.jofti.util.ReflectionUtil; 29 30 public class NativeQueryParser extends AbstractParser implements IQueryParser { 31 32 33 private static Log log = LogFactory.getLog(ParserManager.class); 34 35 36 37 public NativeQueryParser(final int cachedQueries,ClassIntrospector introspector){ 38 super(cachedQueries,introspector); 39 } 40 41 public NativeQueryParser(ClassIntrospector introspector){ 42 this(100, introspector); 43 } 44 45 public IParsedQuery parseQuery(IndexQuery originalQuery) 46 throws JoftiException { 47 try{ 48 return parseQuery(((SQLQuery)originalQuery).getQuery(),originalQuery); 49 } catch (ClassCastException ce){ 50 throw new JoftiException("Class Query is no longer supported - use SQLQuery"); 51 } 52 } 53 54 55 public IParsedQuery getQuery(String name){ 56 57 ParsedQuery query = null; 58 synchronized (lockObject) { 59 query = (ParsedQuery) compiledQueries.get(name); 60 } 61 if (query != null){ 62 SQLQueryWrapper wrapper = new SQLQueryWrapper(query); 63 64 65 return wrapper; 66 } 67 return query; 68 69 } 70 71 public IParsedQuery parseQuery(String name, IndexQuery originalQuery) 72 throws JoftiException { 73 74 SQLQuery tempQuery = (SQLQuery) originalQuery; 76 77 78 ParsedQuery parsedQuery = null; 79 80 synchronized (lockObject) { 82 parsedQuery = (ParsedQuery) compiledQueries.get(name); 83 } 84 85 if (parsedQuery == null) { 87 if (log.isDebugEnabled()) { 89 log.debug("parsing new query " + ((SQLQuery) originalQuery).getQuery()); 90 } 91 93 parsedQuery = parseQuery(new ParsedQuery(), tempQuery); 94 95 synchronized (lockObject) { 97 compiledQueries.put(name, parsedQuery); 98 } 99 } 100 101 SQLQueryWrapper wrapper = new SQLQueryWrapper(parsedQuery); 102 103 105 return wrapper; 106 107 108 } 109 110 111 public ParsedQuery parseQuery(ParsedQuery parsedQuery, IndexQuery originalQuery) throws JoftiException{ 112 113 114 115 String query =((SQLQuery) originalQuery).getQuery(); 116 Reader input =null; 118 try { 119 input = new StringReader (query); 120 121 CommonLexer lexer = new CommonLexer(input); 122 123 SQLQueryParser parser = new SQLQueryParser(lexer); 124 parser.statement(); 125 126 127 AST orderStatement =null; 129 AST ast = parser.getAST(); 130 AST selectStatement = null; 131 132 133 if ( ast == null || ast.getFirstChild() == null){ 134 135 throw new JoftiException("SQLQuery statement '" + formatQueryForError(query) + "' is not of format 'select <classname(s)> [from <namespace>] where <condition(s)>'"); 136 } 137 if (log.isDebugEnabled()){ 138 log.debug(ast.toStringTree()); 139 } 140 AST expression =null; 141 if (ast.getType() == CommonLexerTokenTypes.ORDER){ 143 orderStatement =ast; 144 ast = ast.getFirstChild(); 146 } 147 148 149 if (ast.getFirstChild().getType() == CommonLexerTokenTypes.FROM){ 150 String nameSpace = parseNameSpace(ast.getFirstChild().getFirstChild().getNextSibling()); 151 152 if (originalQuery instanceof INameSpaceAware){ 153 ((INameSpaceAware)originalQuery).setNameSpace(nameSpace); 154 } 155 parsedQuery.setNameSpace(nameSpace); 156 selectStatement = ast.getFirstChild().getFirstChild(); 157 expression = ast.getFirstChild().getNextSibling(); 158 }else{ 159 selectStatement = ast.getFirstChild(); 160 162 expression = selectStatement.getNextSibling(); 163 } 164 165 AST classes= selectStatement.getFirstChild(); 167 if (classes == null){ 168 throw new JoftiException("SQLQuery must contain a single className with no alias or every className must have an alias in query:"+ formatQueryForError(query)); 169 170 } 171 172 parsedQuery = parseClasses(classes, parsedQuery); 173 174 175 177 if(parsedQuery.getAliasMap() != null && parsedQuery.getAliasMap().size()>0){ 179 Iterator it = parsedQuery.getAliasMap().values().iterator(); 180 int size =parsedQuery.getAliasMap().size(); 181 for (int i = 0;i<size;i++){ 182 Object obj = it.next(); 183 parsedQuery.getFieldReturnMap().put(obj,null); 184 } 185 } 186 187 188 if (log.isDebugEnabled()){ 189 190 log.debug(expression.getText()); 191 } 192 193 Stack stack = new Stack (); 194 195 stack = parseWherePredicates(expression,stack,parsedQuery); 196 197 if (log.isDebugEnabled()){ 198 log.debug(stack); 199 } 200 201 Stack temp = new Stack (); 203 204 boolean predicateElement =false; 205 206 while (stack.size() !=0){ 207 Object obj = stack.pop(); 208 if (predicateElement){ 209 if (obj instanceof IPredicate){ 210 throw new JoftiException("SQLQuery not formatted correctly a join operator must seperate two predicates"); 211 } 212 predicateElement =false; 213 } else{ 214 if (obj instanceof Operator){ 215 throw new JoftiException("SQLQuery not formatted correctly a join operator must seperate two predicates"); 216 } 217 predicateElement =true; 218 } 219 temp.push(obj); 220 } 221 222 223 parsedQuery.setPredicates(temp); 224 225 if (orderStatement != null){ 226 parsedQuery = parseOrder(orderStatement, parsedQuery); 227 } 228 } catch (Throwable t){ 229 if (t instanceof JoftiException){ 230 throw (JoftiException)t; 231 }else{ 232 throw new JoftiException("SQLQuery statement '" + formatQueryForError(query) + "' is not of format 'select <classname(s)> where <condition(s)>'",t); 233 } 234 235 }finally { 236 try { 237 if (input != null){ 238 input.close(); 239 } 240 } catch (IOException e){ 241 } 243 } 244 245 246 return parsedQuery; 247 248 249 } 250 251 252 253 254 private String parseNameSpace(AST expression) throws JoftiException{ 255 256 String nameSpace =""; 257 while (expression != null){ 258 259 nameSpace = nameSpace + expression.getText(); 260 expression = expression.getNextSibling(); 261 262 } 263 if (log.isDebugEnabled()){ 264 log.debug("name space:" + nameSpace); 265 } 266 return nameSpace; 267 } 268 269 270 271 272 private ParsedQuery parseClasses(AST classes, ParsedQuery query) throws JoftiException{ 273 AST node = classes; 275 if (node.getType() != CommonLexerTokenTypes.ALIAS_IDENTIFIER){ 276 Class clazz = null; 277 try{ 278 clazz = ReflectionUtil.classForName(node.getText()); 279 }catch (Exception e){ 280 throw new JoftiException("Class "+ node.getText() + " cannot be constructed in query",e); 281 } 282 query.setClassName(clazz); 283 }else{ 284 do{ 285 if (log.isDebugEnabled()){ 287 log.debug("alias found for class " + node.getFirstChild().toStringTree() + " of " +node.getFirstChild().getNextSibling().toStringTree()); 288 } 289 Class clazz =null; 290 try { 291 clazz = ReflectionUtil.classForName(node.getFirstChild().getText()); 292 } catch (Exception e){ 293 throw new JoftiException("Class "+ node.getFirstChild().getText() + " cannot be parsed in query",e); 294 } 295 query.getAliasMap().put(node.getFirstChild().getNextSibling().getText(),clazz ); 296 node = node.getNextSibling(); 297 }while (node != null); 298 } 299 return query; 300 301 302 } 303 304 private String formatQueryForError(String query){ 305 if (query.lastIndexOf(";") != query.length()){ 306 return query.substring(0,query.length()-1); 307 }else{ 308 return query; 309 } 310 } 311 312 } 313 | Popular Tags |