1 package com.jofti.parser; 2 3 import java.io.Reader ; 4 import java.io.StringReader ; 5 import java.util.Comparator ; 6 import java.util.HashMap ; 7 import java.util.Iterator ; 8 import java.util.LinkedHashMap ; 9 import java.util.List ; 10 import java.util.Map ; 11 import java.util.Stack ; 12 13 import org.apache.commons.logging.Log; 14 import org.apache.commons.logging.LogFactory; 15 16 import antlr.collections.AST; 17 18 import com.jofti.api.IndexQuery; 19 import com.jofti.core.IParsedQuery; 20 import com.jofti.core.IPredicate; 21 import com.jofti.exception.JoftiException; 22 import com.jofti.introspect.ClassIntrospector; 23 import com.jofti.parser.ejb.EJB3QueryParser; 24 import com.jofti.query.EJBQuery; 25 import com.jofti.util.ArrayComparator; 26 import com.jofti.util.CompositeComparator; 27 import com.jofti.util.ReflectionComparator; 28 import com.jofti.util.ReflectionUtil; 29 30 38 public class EJBQueryParser extends AbstractParser implements IQueryParser { 39 40 public EJBQueryParser(final int cachedQueries, ClassIntrospector introspector) { 42 super(cachedQueries, introspector); 43 } 44 45 public EJBQueryParser( ClassIntrospector introspector) { 47 this(100, introspector); 48 } 49 50 private static Log log = LogFactory.getLog(ParserManager.class); 51 52 55 public IParsedQuery parseQuery(IndexQuery originalQuery) 56 throws JoftiException { 57 58 59 return parseQuery(((EJBQuery)originalQuery).getQuery(),originalQuery); 60 61 } 62 63 public IParsedQuery getQuery(String name){ 64 65 ParsedQuery query = null; 66 synchronized (lockObject) { 67 query = (ParsedQuery) compiledQueries.get(name); 68 } 69 if (query != null){ 70 ParsedQueryWrapper wrapper = new ParsedQueryWrapper(query); 71 72 wrapper.setNamedValueMap(new HashMap ()); 74 75 return wrapper; 76 } 77 return null; 78 79 } 80 81 public IParsedQuery parseQuery(String name, IndexQuery originalQuery) 82 throws JoftiException { 83 84 EJBQuery tempQuery = (EJBQuery) originalQuery; 86 87 88 89 ParsedQuery parsedQuery = null; 90 91 synchronized (lockObject) { 93 parsedQuery = (ParsedQuery) compiledQueries.get(name); 94 } 95 96 if (parsedQuery == null) { 98 if (log.isDebugEnabled()) { 100 log.debug("parsing new query " + tempQuery.getQuery()); 101 } 102 104 parsedQuery = parseQuery(new ParsedQuery(), tempQuery.getQuery()); 105 106 parsedQuery.setFirstResult(tempQuery.getFirstResult()); 107 108 synchronized (lockObject) { 110 compiledQueries.put(name, parsedQuery); 111 } 112 } 113 114 118 ParsedQueryWrapper wrapper = new ParsedQueryWrapper(parsedQuery); 119 120 wrapper.setNamedValueMap(tempQuery.getParameterMap()); 122 123 124 wrapper.setFirstResult(tempQuery.getFirstResult()); 125 wrapper.setMaxResults(tempQuery.getMaxResults()); 126 127 return wrapper; 128 } 129 130 private ParsedQuery parseQuery(ParsedQuery parsedQuery, String selectClause) 131 throws JoftiException { 132 Reader input = null; 133 try { 134 input = new StringReader (selectClause); 135 136 CommonLexer lexer = new CommonLexer(input); 137 138 EJB3QueryParser parser = new EJB3QueryParser(lexer); 139 140 parser.queryStatement(); 141 142 AST ast = parser.getAST(); 143 AST selectStatement = null; 144 145 if (ast == null || ast.getFirstChild() == null) { 146 147 throw new JoftiException( 148 "Query '" 149 + selectClause 150 + "' is not of format 'SELECT variable[[,] variable]* FROM Class [AS] identifier[,Class [AS] identifier] WHERE predicate [ORDER BY identifier [ASC|DESC]]*'"); 151 } 152 if (log.isDebugEnabled()) { 153 log.debug(ast.toStringTree()); 154 } 155 156 parsedQuery = parseClause(ast, parsedQuery); 157 158 } catch (Exception e) { 159 throw new JoftiException(e); 160 } finally { 161 try { 162 input.close(); 163 } catch (Exception e) { 164 log.warn("problem closing reader", e); 165 } 166 } 167 return parsedQuery; 168 } 169 170 private ParsedQuery parseClause(AST ast, ParsedQuery parsedQuery) 171 throws JoftiException { 172 AST orderNode =null; 173 do { 174 switch (ast.getType()) { 176 case CommonLexerTokenTypes.NAMESPACE: 177 parsedQuery = parseNameSpace(ast.getFirstChild() 179 .getNextSibling(), parsedQuery); 180 181 ast = ast.getFirstChild(); 183 break; 184 case CommonLexerTokenTypes.WHERE: 185 parsedQuery = parseFrom(ast.getFirstChild().getFirstChild() 187 .getNextSibling(), parsedQuery); 188 189 191 parsedQuery = parseWhere(ast.getFirstChild().getNextSibling(), 192 parsedQuery); 193 194 ast = ast.getFirstChild().getFirstChild(); 196 break; 197 case CommonLexerTokenTypes.FROM: 199 parsedQuery = parseFrom(ast.getFirstChild().getNextSibling(), 200 parsedQuery); 201 202 ast = ast.getFirstChild(); 204 break; 205 207 case CommonLexerTokenTypes.SELECT: 208 parsedQuery = parseSelect(ast, parsedQuery); 209 210 ast = ast.getFirstChild(); 212 break; 213 case CommonLexerTokenTypes.ORDER: 214 orderNode =ast; 215 ast = ast.getFirstChild(); 218 break; 219 default: 221 ast = ast.getFirstChild(); 222 break; 223 } 224 } while (ast != null); 225 226 if (orderNode != null){ 227 parsedQuery = parseOrder(orderNode, parsedQuery); 228 } 229 return parsedQuery; 230 } 231 232 private ParsedQuery parseWhere(AST ast, ParsedQuery parsedQuery) 233 throws JoftiException { 234 Stack stack = new Stack (); 235 236 stack = parseWherePredicates(ast, stack, parsedQuery); 237 238 if (log.isDebugEnabled()) { 239 log.debug(stack); 240 } 241 242 Stack temp = new Stack (); 244 245 boolean predicateElement = false; 246 247 while (stack.size() != 0) { 248 Object obj = stack.pop(); 249 if (predicateElement) { 250 if (obj instanceof IPredicate) { 251 throw new JoftiException( 252 "Query not formatted correctly a join operator must seperate two predicates"); 253 } 254 predicateElement = false; 255 } else { 256 if (obj instanceof Operator) { 257 throw new JoftiException( 258 "Query not formatted correctly a join operator must seperate two predicates"); 259 } 260 predicateElement = true; 261 } 262 temp.push(obj); 263 } 264 265 parsedQuery.setPredicates(temp); 266 return parsedQuery; 267 } 268 269 private ParsedQuery parseNameSpace(AST expression, ParsedQuery query) 270 throws JoftiException { 271 272 AST node = expression; 273 String nameSpace = ""; 274 do { 275 if (log.isDebugEnabled()) { 276 log.debug("parsing select for " + node.toStringTree()); 277 } 278 279 nameSpace = nameSpace + node.getText(); 280 node = node.getNextSibling(); 281 282 } while (node != null); 283 284 query.setNameSpace(nameSpace); 285 return query; 286 287 } 288 289 private ParsedQuery parseSelect(AST expression, ParsedQuery query) 290 throws JoftiException { 291 292 AST node = expression.getFirstChild(); 294 295 do { 296 298 if (log.isDebugEnabled()) { 299 log.debug("parsing select for " + node.toStringTree()); 300 } 301 addToFieldMap(query.getAliasMap(), query.getResultFieldsMap(), node 303 .getText()); 304 node = node.getNextSibling(); 305 306 } while (node != null); 307 308 return query; 309 310 } 311 312 313 314 private ParsedQuery parseFrom(AST expression, ParsedQuery query) 315 throws JoftiException { 316 317 AST node = expression; 319 320 do { 321 if (node.getType() == CommonLexerTokenTypes.ALIAS_IDENTIFIER) { 323 if (log.isDebugEnabled()) { 324 log.debug("alias found for class " 325 + node.getFirstChild().toStringTree() 326 + " of " 327 + node.getFirstChild().getNextSibling() 328 .toStringTree()); 329 } 330 331 Class clazz = null; 333 try { 334 clazz = ReflectionUtil.classForName(node.getFirstChild() 335 .getText()); 336 } catch (Exception e) { 337 throw new JoftiException("Class " 338 + node.getFirstChild().getText() 339 + " cannot be parsed in From clause", e); 340 } 341 if (clazz.isPrimitive() || clazz == Boolean .class){ 342 clazz = introspector.boxPrimitive(clazz); 343 } 344 query.getAliasMap().put( 345 node.getFirstChild().getNextSibling().getText(), clazz); 346 node = node.getNextSibling(); 347 } else { 348 352 354 Class clazz = null; 356 try { 357 clazz = ReflectionUtil.classForName(node.getText()); 358 } catch (Exception e) { 359 throw new JoftiException("Class " + node.getText() 360 + " cannot be parsed in From clause", e); 361 } 362 if (clazz.isPrimitive() || clazz == Boolean .class){ 363 clazz = introspector.boxPrimitive(clazz); 364 } 365 query.getAliasMap().put(node.getNextSibling().getText(), clazz); 366 node = node.getNextSibling().getNextSibling(); 368 } 369 370 } while (node != null); 371 372 return query; 373 374 } 375 376 377 378 379 380 381 382 private void addToFieldMap(Map aliasMap, Map returnMap, String alias) 383 throws JoftiException { 384 int aliasSeperator = alias.indexOf('.'); 385 386 if (aliasSeperator > 0) { 387 Class clazz = getClassForAlias(aliasMap, alias); 388 ClassFieldMethods fieldSet = (ClassFieldMethods) returnMap.get(clazz); 389 if (fieldSet == null) { 390 fieldSet = new ClassFieldMethods(clazz, null); 391 if (fieldSet.getFieldMap() == null) { 392 fieldSet.setFieldMap(new LinkedHashMap ()); 393 } 394 returnMap.put(clazz,fieldSet); 395 } 396 397 400 String attribute = alias.substring(aliasSeperator + 1, alias.length()); 401 402 if (fieldSet.getFieldMap().containsKey(attribute)){ 403 throw new JoftiException("Field "+ attribute + " is already part of the return set for "+clazz); 404 } 405 Object [] methods = introspector.getMethodsForAttribute(clazz,attribute); 406 if (methods == null || methods.length ==0){ 407 throw new JoftiException("Attribute "+ attribute + " is not valid for "+ clazz); 409 }else{ 410 fieldSet.getFieldMap().put(attribute,methods); 411 } 412 413 } else { 414 if (!aliasMap.containsKey(alias)) { 415 throw new JoftiException("select for identifier " + alias 416 + " is not mentioned in from clause"); 417 } else if (returnMap.containsKey(aliasMap.get(alias))) { 418 if (returnMap.get(aliasMap.get(alias)) == null || 419 ((ClassFieldMethods)returnMap.get(aliasMap.get(alias))).getFieldMap() == null || 420 ((ClassFieldMethods)returnMap.get(aliasMap.get(alias))).getFieldMap().size()==0 ){ 421 throw new JoftiException(""+ aliasMap.get(alias) + 422 " under alias " + alias + " is listed more than once in select clause"); 423 }else 424 throw new JoftiException(" "+ aliasMap.get(alias) + 425 " as whole object under alias " + alias +" cannot be selected if fields from class are already in select clause"); 426 } 427 428 returnMap.put(aliasMap.get(alias), new ClassFieldMethods( 429 (Class ) aliasMap.get(alias), null)); 430 431 } 432 } 433 } | Popular Tags |